home *** CD-ROM | disk | FTP | other *** search
/ Just Call Me Internet / Just Call Me Internet.iso / prog / atari / m2 / cat3src / cat / editfunc.i < prev    next >
Text File  |  1997-10-26  |  103KB  |  3,387 lines

  1. IMPLEMENTATION MODULE EditFuncs;
  2.  
  3. (*$Z+*)
  4. (*$Y+*) 
  5.  
  6. FROM SYSTEM     IMPORT  ADDRESS, ADR, TSIZE, CADR, LOC, LONGWORD, WORD, CALLSYS;
  7.  
  8. (* Megamax-Lib *)
  9.  
  10. FROM Storage    IMPORT ALLOCATE, DEALLOCATE, Inconsistent;
  11.  
  12. FROM GrafBase   IMPORT LongRect, Rectangle, Point;
  13.  
  14. IMPORT Storage, Strings, BinOps, Block, StrConv, 
  15.        MOSGlobals, Keyboard, Characters, Lists;
  16.  
  17. FROM Keyboard  IMPORT SpecialCode;
  18.  
  19. (* MagicLib *)
  20. IMPORT MagicAES, MagicVDI, MagicDOS, MagicBIOS, MagicSys, MagicFSM, 
  21.        mtAlerts, mtAppl, mtDials, mtUtils, mtTextfiles;
  22.  
  23. (* CAT Module *)
  24. IMPORT CatFiles, MTE, Clip;
  25.  
  26. FROM Void       IMPORT v;
  27.  
  28. IMPORT FontSelect;
  29.  
  30. (* Editor  *)
  31. FROM EditTypes  IMPORT EDITPTR, EDITOR, aLinePtr, aLineDesc, aLine, textPtr, aMark, 
  32.                        userProcType, userGetRectProc, drawUserProc, userCloseProc, 
  33.                        deskSize, pixOff, undoType, SuchFlags, SuchModus, searchDir, 
  34.                        searchPos, searchCount, CAT, CharSet, TrennSet, UmbruchSet,
  35.                        userKeyProc, userTopProc, userUntopProc, theDrawLine, aBufferPtr, 
  36.                        LFIRST, LNEXT;
  37.  
  38. FROM EditGlobals        IMPORT  ClipWork, MouseArrow, MouseBusy, 
  39.                                 HideMouse, ShowMouse, HideCursor, 
  40.                                 ShowCursor, drawCursor, RowToIndex, 
  41.                                 SetDocument, CursorIsOn, AllocNew;
  42. FROM EditTools          IMPORT  SetInfoLine, SetEditTitle, ShowFileChanged, 
  43.                                 SetCurrLine, SetStartLine, getCharPos, 
  44.                                 SaveLine, SaveOp, DeleteLine, 
  45.                                 Undo, NewBlockToUndoBuffer,  
  46.                                 SetBlockstart, SetBlockend, ClearBlock,
  47.                                 GetClickLineAndRow, TestBlockMarksAndSwap, ToWordEnd,
  48.                                 ToWordStart, MarkLine, MarkWord, MarkBlock, 
  49.                                 ToBlockmark, SearchWord, ReplaceWord, FreeUndoBuffer,
  50.                                 UpdateCurrLine, ToLineEnd;
  51.                                 
  52. FROM EditDraw           IMPORT  drawLine, redrawLine, 
  53.                                 redrawLines, redrawWdw,
  54.                                 redrawLineArea, scrollRegion, CenterCurrline; 
  55.  
  56. IMPORT CatEdit;         (* Circul„rer Import! *)
  57. IMPORT EditGlobals;
  58. IMPORT EditBase;
  59. IMPORT EditTools;
  60. IMPORT WdwManager;
  61. IMPORT Printer;
  62. IMPORT ConfVars;
  63. IMPORT Varnames;
  64. IMPORT CatGlobal;
  65. IMPORT UUDecode;
  66.  
  67. (*$? NOT CAT:
  68. (* Fr Compilierung im Speicher *)
  69. IMPORT Loader, Directory, Paths, ShellMsg, PathEnv;
  70. *)
  71. IMPORT FileNames;
  72.  
  73. (*$? CAT:
  74. IMPORT mtDir;
  75. *)
  76. (*$? CAT:
  77. CONST   progName = 'CAT:';
  78. *)
  79. (*$? NOT CAT:
  80. CONST   progName = 'Fred:';
  81. *)
  82.  
  83. CONST   outOfMem = '[3]['+progName+'|Nicht genug|freier Speicher][[Abbruch]';
  84.         readErr  = '[3]['+progName+'|Konnte Text nicht lesen!|Editor wird nicht|ge”ffnet!][[Abbruch]';
  85.         noTextErr= '[3]['+progName+'|Dies ist kein ASCII-Text!|Das kann ich leider|nicht laden.][[Abbruch]';
  86.         askRepl  = '[2]['+progName+'|Text ersetzen: |Sie k”nnen (J)a, (N)ein |oder (A)bbruch eingeben|oder diesen Dialog beantworten!][[Ja|[Nein|:[Abbruch]';
  87.         
  88.         compileMsg  = ' Compiling...'+0C;
  89.         
  90.         CR      = 15C;
  91.         LF      = 12C;
  92.         TAB     = 11C;
  93.  
  94. TYPE
  95.      Str128     = ARRAY [0..127] OF CHAR;
  96.      numSet     = SET OF [0..255];
  97.  
  98. (*$? NOT CAT: 
  99.  
  100. (* Variablen fr Compilierung im Speicher *)
  101. VAR  callRes    : Loader.LoaderResults;
  102.      callMsg    : Strings.String;
  103.      exitCode   : INTEGER;
  104.  
  105.      compLine   : LONGINT;
  106.      compEd     : EDITPTR;
  107.  
  108. (*
  109.  Auszug aus dem GME:
  110.  -------------------
  111.  * Diese Prozedur wird vom Compiler pro Zeile aufgerufen, wenn ihre
  112.  * Adresse in Textform (ggf. auch Hex mit "$" voran) nach der Option
  113.  * "/^" in der Argumentzeile beim Compileraufruf angegeben wird.
  114.  * Zus„tzlich sollte noch die Option "/Q" angegeben werden, um weitere
  115.  * Ausgaben des Compilers zu unterdrcken.
  116.  *)
  117.  
  118. VAR compEOF : ARRAY[0..3] OF CHAR;
  119.  
  120. (*$Z-*)
  121. PROCEDURE doCompilerLine (): textPtr;
  122.   VAR p : textPtr;
  123.   BEGIN
  124.       IF compLine < compEd^.totalLineNr THEN
  125.         v.bool := EditBase.GetLine (compEd, compLine, theDrawLine, v.int);
  126.         p:= ADR (theDrawLine); (* n„chste Zeile, mit 0C abgeschlossen! *)
  127.         DEC (v.int);
  128.         WHILE (v.int >= 0) & (ORD(theDrawLine[v.int]) < 32) DO theDrawLine[v.int] := 0C END;
  129.         CALLSYS (1, 4201, CADR("cLine %ld: %s"), compLine, p);
  130.         INC (compLine);
  131.       ELSE
  132.         compEOF[0]:= 3C;  (* Programmende *)
  133.         compEOF[1]:= 0C;
  134.         p:= ADR (compEOF);
  135.       END;
  136.       RETURN p
  137.   (*
  138.     ASSEMBLER
  139.         LEA     compLine,A0
  140.         MOVE.L  (A0),A1
  141.         BEQ     atEOF
  142.         MOVE.L  compLine.zeile.text(A1),(A3)+   
  143.         MOVE.L  compLine.next(A1),(A0)
  144.  
  145.         RTS
  146.  
  147.       atEOF
  148.         MOVE.W  #$0300,compEOF
  149.         MOVE.L  #compEOF,(A3)+
  150.     END;
  151.   *)
  152.   END doCompilerLine;
  153. (*$Z+*)
  154.  
  155. PROCEDURE call ( ed : EDITPTR; VAR modname: ARRAY OF CHAR; args: ARRAY OF CHAR;
  156.                  stackSize: LONGCARD; tool:BOOLEAN );
  157.   
  158.   VAR sufstr            : ARRAY[0..2] OF CHAR;
  159.       dummy             : ARRAY[0..12] OF CHAR;
  160.       name, path,
  161.       oldPath           : Str128;
  162.       prevStackSize     : LONGCARD;
  163.  
  164.   BEGIN
  165.     Strings.Assign (modname, name, v.bool);
  166.     Strings.Upper (name);
  167.  
  168.     FileNames.SplitPath (name, path, dummy);
  169.     FileNames.SplitName (dummy,dummy,sufstr);
  170.  
  171.     Directory.GetDefaultPath (oldPath);
  172.     IF (path[0] = 0C) AND NOT tool THEN
  173.       (* Ist kein Pfad angegeben, bleibt bei Tools und
  174.        * Systemprgs der akt. Pfad erhalten
  175.        *)
  176.       Paths.SearchFile (name, ShellMsg.StdPaths, Paths.fromStart, v.bool, name);
  177.       FileNames.SplitPath (name, path, dummy);
  178.     END;
  179.     Directory.SetDefaultPath (path, v.int);
  180.     
  181.     prevStackSize:= Loader.DefaultStackSize;
  182.  
  183.     IF stackSize # 0 THEN Loader.DefaultStackSize:= stackSize END;
  184.  
  185.     Loader.CallModule (name, ShellMsg.StdPaths, args, NIL, exitCode, callMsg, callRes);
  186.  
  187.     Loader.DefaultStackSize:= prevStackSize;
  188.     
  189.     Directory.SetDefaultPath (oldPath, v.int);
  190.  
  191.   END call;
  192.  
  193. (*  callComp -- Calls the compiler to compile the file in the editor 'ed'.
  194.  *)
  195.  
  196.  
  197. PROCEDURE callComp (ed : EDITPTR);
  198.  
  199.  
  200. CONST   CompilerStackSize = 16000;
  201.  
  202.   VAR i:INTEGER;
  203.       s,msg:Str128;
  204.       adr : RECORD a,b : ADDRESS; END;
  205.  
  206.   BEGIN
  207.     (*  String mit Compileroptionen aufbauen.
  208.      *)
  209.     MouseBusy();
  210.     
  211.     WITH ShellMsg.CompilerParm DO
  212.       IF shortMsgs THEN s:= ' -Q' ELSE s:= ' +Q' END;
  213.       Strings.Append (' ', s, v.bool);
  214.       Strings.Append (ShellMsg.CompilerArgs, s, v.bool);
  215.       IF ~ Strings.Empty (ShellMsg.MainOutputPath) THEN
  216.         Strings.Append (' /O', s, v.bool);
  217.         Strings.Append (ShellMsg.MainOutputPath, s, v.bool);
  218.       END;
  219.       IF protocol THEN
  220.         Strings.Append (' /C', s, v.bool);
  221.         Strings.Append (StrConv.CardToStr (protWidth, 0), s, v.bool);
  222.         Strings.Append (' /P', s, v.bool);
  223.         Strings.Append (protName, s, v.bool);
  224.       END;
  225.       (* Parameter fr Quiet und im Speicher *)
  226.       Strings.Append (' /Q /^',s, v.bool);
  227.       Strings.Append (StrConv.LHexToStr(ADDRESS(doCompilerLine),0),s, v.bool);
  228.     END;
  229.     
  230.     Strings.Assign (compileMsg, ed^.errMsg, v.bool);
  231.     WdwManager.SetWdwInfoline (ed^.wdw, ed^.errMsg);
  232.     IF ed^.fileName.length > 0
  233.     THEN
  234.       Strings.Concat (ed^.fileName.text^,s, s, v.bool);
  235.     ELSE
  236.       Strings.Concat ('namenlos.txt', s, s, v.bool);
  237.     END;
  238.     
  239.     compLine := 0;
  240.  
  241.     call (ed, ShellMsg.CompilerParm.name, s,
  242.           CompilerStackSize, TRUE);
  243.     
  244.     IF callRes # Loader.noError THEN
  245.       (* Fehlermeldung, Compiler nicht gefunden *)
  246.     ELSE
  247.       IF exitCode # 0
  248.       THEN
  249.         WITH ed^ DO 
  250.           errLine := ShellMsg.TextLine;
  251.           errRow := ShellMsg.TextCol-1;
  252.           Strings.Assign (ShellMsg.ErrorMsg, errMsg, v.bool);
  253.         END;
  254.         showError (ed);
  255.       ELSE
  256.         Strings.Assign (ShellMsg.CodeName, ed^.errMsg, v.bool);
  257.         Strings.Append (', ', ed^.errMsg, v.bool);
  258.         Strings.Append (StrConv.CardToStr (ShellMsg.CodeSize,0), ed^.errMsg, v.bool);
  259.         Strings.Append (' Bytes.', ed^.errMsg, v.bool);
  260.         WdwManager.SetWdwInfoline (ed^.wdw, ed^.errMsg);
  261.       END;
  262.     END;
  263.     HideMouse ();
  264.     MouseArrow();
  265.     ShowMouse (FALSE);
  266.   END callComp;
  267. *)
  268.  
  269.                 (* "Suchfunktionen" *)
  270.  
  271. PROCEDURE FindEditor ( wdw : INTEGER) : EDITPTR;
  272.   VAR ed : EDITPTR;
  273. BEGIN
  274.   ed := editList;
  275.   WHILE ed # NIL DO
  276.     IF ed^.wdw = wdw THEN RETURN ed END;
  277.     ed := ed^.nextEdit;
  278.   END;
  279.   RETURN NIL;
  280. END FindEditor;
  281.  
  282. PROCEDURE GetEditNumber (wdw : INTEGER) : INTEGER;
  283. (* Gibt die interne Nummer des Editors zurck *)
  284.   VAR ed : EDITPTR;
  285. BEGIN
  286.   ed := FindEditor (wdw);
  287.   IF ed # NIL
  288.   THEN 
  289.     RETURN ed^.number
  290.   ELSE
  291.     RETURN -1
  292.   END;
  293. END GetEditNumber;
  294.  
  295. PROCEDURE OutOfMem ();
  296. BEGIN
  297.   (*$? CAT:
  298.   MTE.noMemAlert ();
  299.   *)
  300.   (*$? NOT CAT:
  301.   MTE.info (outOfMem);
  302.   *)
  303. END OutOfMem;
  304.  
  305. PROCEDURE findNext (text : textPtr; fromPos, l : INTEGER; tSet : CharSet) : INTEGER;
  306.   VAR z : INTEGER;
  307.       ch : CHAR;
  308. BEGIN
  309.   z := fromPos;
  310.   WHILE (z < l) AND ~(text^[z] IN CharSet{0C, CR, LF}) AND ~(text^[z] IN tSet) DO  INC(z);  END;
  311.   WHILE (z < l) AND ~(text^[z] IN CharSet{0C, CR, LF}) AND  (text^[z] IN tSet) DO  INC(z);  END;
  312. (*
  313.   WHILE (z < l) & ~(text^[z] IN tSet) DO INC (z) END;
  314.   ch := text^[z];
  315.   IF (ch # CR) & (ch # LF) THEN
  316.     WHILE (z < l) & (text^[z] = ch) DO INC (z) END;
  317.   END;
  318. (*  IF z = fromPos
  319.   THEN
  320.     RETURN findNext (text, z+1, l, tSet);
  321.   END;
  322. *)
  323. *)
  324.   RETURN z;
  325. END findNext;
  326.  
  327. PROCEDURE FindNext(ed : EDITPTR; umbr : BOOLEAN; l : INTEGER): INTEGER;
  328. VAR z    : INTEGER;
  329.     text : textPtr;
  330.     tSet : CharSet;
  331. BEGIN
  332.   WITH ed^ DO 
  333.     IF umbr THEN 
  334.       RETURN findNext (editLine.text, currRow, l, UmbruchSet);
  335.     ELSE 
  336.       RETURN findNext (editLine.text, currRow, l, TrennSet);
  337.     END;
  338.   END (* WITH ed^ DO *);
  339. END FindNext;
  340.  
  341. PROCEDURE findLast (text : textPtr; fromPos : INTEGER; tSet : CharSet) : INTEGER;
  342.   VAR z : INTEGER;
  343.       ch: CHAR;
  344. BEGIN
  345.   z := fromPos;
  346.   (*
  347.   IF (z>0) & (text^[z] = 0C) & (text^[z-1] IN tSet)
  348.   THEN DEC (z) END;
  349.   (*
  350.   IF (z > 0) & ~(text^[z] IN tSet) & (text^[z-1] IN tSet) THEN 
  351.     WHILE (z > 0) & ~(text^[z] IN tSet) DO DEC(z) END;
  352.   END;
  353.   *)
  354.   IF text^[z] IN tSet THEN
  355.     WHILE (z > 0) & (text^[z] IN tSet)  DO DEC(z) END;
  356.   ELSE
  357.     WHILE (z > 0) & ~(text^[z] IN tSet) DO DEC(z) END;
  358.     ch := text^[z];
  359.     WHILE (z > 0) & (text^[z] = ch)  DO DEC(z) END;
  360.   END;
  361.   (*
  362.   WHILE (z > 0) & (text^[z] IN tSet)  DO DEC(z) END;
  363.   *)
  364.   WHILE (z > 0) & ~(text^[z] IN tSet) DO DEC(z) END;
  365.   IF (z # fromPos) & (z # 0) THEN INC(z) END;
  366.   *)
  367.   WHILE (z > 0) AND (text^[z-1] IN tSet) DO  DEC(z);  END;
  368.   WHILE (z > 0) AND ~(text^[z-1] IN tSet) DO  DEC(z);  END;
  369.   RETURN z;
  370. END findLast;
  371.  
  372. PROCEDURE FindLast(ed : EDITPTR; umbr : BOOLEAN): INTEGER;
  373. BEGIN
  374.   WITH ed^ DO 
  375.     IF umbr THEN 
  376.       RETURN findLast (editLine.text, currRow, UmbruchSet);
  377.     ELSE 
  378.       RETURN findLast (editLine.text, currRow, TrennSet);
  379.     END;
  380.   END (* WITH ed^ DO *);
  381. END FindLast;
  382.  
  383. PROCEDURE CursorDown (ed : EDITPTR; ctrl : BOOLEAN);
  384. BEGIN
  385.   WITH ed^ DO
  386.     HideMouse();
  387.     HideCursor(ed);
  388.     IF block & ~readOnly THEN 
  389.       SetCurrLine (ed, blocks[0].blockEnd.line);
  390.       currRow := blocks[0].blockEnd.row;
  391.       EditGlobals.FixCursorPos (ed);
  392.       ClearBlock (ed); 
  393.     END;
  394.     IF (currLineNr - StartLine  = LONG(windLines-1)) OR (readOnly & ~multiBlockMark) THEN      (* hier nur ganze Zeile *)
  395.       IF ctrl
  396.       THEN
  397.         WdwManager.PageDown (ed^.wdw);
  398.       ELSE
  399.         WdwManager.ScrollDown(ed^.wdw, 1);
  400.       END;
  401.     ELSE
  402.       IF ctrl 
  403.       THEN
  404.         SetCurrLine (ed, StartLine + LONG(windLines) - 1) 
  405.       ELSE
  406.         SetCurrLine (ed, currLineNr + 1);
  407.       END;
  408.       currRow := BinOps.LowerInt(currRow, editLen);
  409.       EditGlobals.FixCursorPos (ed);
  410.     END;
  411.     CenterCurrline (ed);
  412.     ShowCursor(ed);
  413.     ShowMouse (FALSE);
  414.   END;
  415. END CursorDown;
  416.  
  417. PROCEDURE CursorUp (ed : EDITPTR; ctrl : BOOLEAN);
  418. BEGIN
  419.   WITH ed^ DO
  420.     HideMouse();
  421.     HideCursor (ed);
  422.     IF block & ~readOnly THEN 
  423.       SetCurrLine (ed, blocks[0].blockStart.line);
  424.       currRow := blocks[0].blockStart.row;
  425.       EditGlobals.FixCursorPos (ed);
  426.       ClearBlock (ed); 
  427.     END;
  428.     IF ((currLineNr = StartLine) & (currLineNr > 0)) OR (readOnly & ~multiBlockMark) THEN
  429.       IF ctrl THEN
  430.         WdwManager.PageUp (ed^.wdw)
  431.       ELSE
  432.         WdwManager.ScrollUp(ed^.wdw, 1);
  433.       END;
  434.     ELSIF ((currLineNr - StartLine) # 0) & (currLineNr > 0) THEN
  435.       IF ctrl THEN
  436.         SetCurrLine (ed, StartLine)
  437.       ELSE
  438.         SetCurrLine (ed, currLineNr-1);
  439.       END;
  440.       currRow := BinOps.LowerInt(currRow, editLen);
  441.       EditGlobals.FixCursorPos (ed);
  442.     END;
  443.     ShowCursor(ed);
  444.     ShowMouse (FALSE);
  445.   END;
  446. END CursorUp;
  447.  
  448. PROCEDURE CursorLeft (ed : EDITPTR; kstate : BITSET);
  449.   VAR l : INTEGER;
  450. BEGIN
  451.   HideMouse();
  452.   HideCursor (ed);
  453.   WITH ed^ DO
  454.     IF block & ~readOnly THEN 
  455.       SetCurrLine (ed, blocks[0].blockStart.line);
  456.       currRow := blocks[0].blockStart.row;
  457.       EditGlobals.FixCursorPos (ed);
  458.       ClearBlock (ed);
  459.       ShowCursor (ed);
  460.       ShowMouse (FALSE);
  461.       RETURN;
  462.     END;
  463.     IF readOnly & ~multiBlockMark
  464.     THEN
  465.       IF CatGlobal.WithShift (kstate) THEN
  466.         WdwManager.PageLeft (ed^.wdw);
  467.       ELSE
  468.         WdwManager.ScrollLeft (ed^.wdw, 1);
  469.       END;
  470.     ELSIF currRow = 0 THEN
  471.       IF currLineNr > StartLine THEN
  472.         SetCurrLine (ed, currLineNr - 1);
  473.         currRow := editLen;
  474.       ELSIF StartLine > 0 THEN
  475.         WdwManager.ScrollUp(ed^.wdw, 1);
  476.         currRow := editLen;
  477.       END;
  478.     ELSIF CatGlobal.WithCtrl (kstate) THEN
  479.       currRow := FindLast(ed, FALSE); 
  480.     ELSIF (0 IN kstate) OR (1 IN kstate) THEN
  481.       currRow := 0; 
  482.     ELSIF currRow > 0 THEN
  483.       DEC(currRow);
  484.     END;
  485.     EditGlobals.FixCursorPos (ed);
  486.   END (* WITH ed^ DO *);
  487.   ShowCursor (ed);
  488.   ShowMouse (FALSE);
  489. END CursorLeft;
  490.  
  491. PROCEDURE CursorRight(ed : EDITPTR; kstate : BITSET);
  492.   VAR l : INTEGER;
  493.       m : aMark;
  494. BEGIN
  495.   HideMouse();
  496.   HideCursor (ed);
  497.   WITH ed^ DO
  498.     IF block & ~readOnly THEN
  499.       SetCurrLine (ed, blocks[0].blockEnd.line);
  500.       currRow := blocks[0].blockEnd.row;
  501.       EditGlobals.FixCursorPos (ed);
  502.       ClearBlock (ed); 
  503.       ShowCursor (ed);
  504.       ShowMouse (FALSE);
  505.       RETURN;
  506.     END;
  507.     IF readOnly & ~multiBlockMark
  508.     THEN
  509.       IF CatGlobal.WithShift (kstate) THEN
  510.         WdwManager.PageRight (ed^.wdw);
  511.       ELSE
  512.         WdwManager.ScrollRight (ed^.wdw, 1);
  513.       END;
  514.     ELSIF (editLine.text^[currRow] = CR) OR (editLine.text^[currRow] = LF)  (* currRow >= l *)
  515.     THEN 
  516.       (* Zeilenende *) 
  517.       IF (currLineNr-StartLine < LONG(windLines)-1) & (currLineNr < totalLineNr - 1) THEN
  518.         SetCurrLine (ed, currLineNr + 1);
  519.         currRow := 0;
  520.       ELSIF currLineNr < totalLineNr - 1
  521.       THEN
  522.         WdwManager.ScrollDown (ed^.wdw, 1);
  523.         currRow := 0;
  524.       END;
  525.     ELSIF kstate = {}
  526.     THEN
  527.       INC (currRow);
  528.     ELSIF CatGlobal.WithCtrl (kstate) THEN
  529.       currRow := FindNext(ed, FALSE, editLen);
  530.     ELSIF (0 IN kstate) OR (1 IN kstate) THEN
  531.       currRow := editLen; 
  532.     END;
  533.     EditGlobals.FixCursorPos (ed);
  534.   END (* WITH ed^ DO *);
  535.   ShowCursor (ed);
  536.   ShowMouse (FALSE);
  537. END CursorRight;
  538.  
  539. PROCEDURE AllUp (text : textPtr);
  540. BEGIN
  541.   Strings.Upper (text^);
  542. END AllUp;
  543.  
  544. PROCEDURE AllLower (text : textPtr);
  545. BEGIN
  546.   Strings.Lower (text^);
  547. END AllLower;
  548.  
  549. PROCEDURE SwapUpperLower (text : textPtr);
  550.   VAR i : INTEGER;
  551. BEGIN
  552.   i := 0;
  553.   LOOP
  554.     IF text^[i] = 0C THEN EXIT END;
  555.     IF Characters.IsUpper (text^[i])
  556.     THEN
  557.       Strings.Lower (text^[i]);
  558.     ELSIF Characters.IsLower (text^[i])
  559.     THEN
  560.       Strings.Upper (text^[i]);
  561.     END;
  562.     INC (i);
  563.   END;
  564. END SwapUpperLower;
  565.  
  566. PROCEDURE Capitalise (text : textPtr);
  567.   VAR i : INTEGER;
  568. BEGIN
  569.   i := 0;
  570.   LOOP
  571.     WHILE (text^[i] IN TrennSet) & (text^[i] # 0C) DO INC (i); END;
  572.     IF text^[i] = 0C THEN EXIT END;
  573.     Strings.Upper (text^[i]);
  574.     INC(i);
  575.     WHILE ~(text^[i] IN TrennSet) & (text^[i] # 0C) DO 
  576.       Strings.Lower (text^[i]);
  577.       INC (i); 
  578.     END;
  579.   END;
  580. END Capitalise;
  581.  
  582. PROCEDURE Mirror (text : textPtr);
  583.   VAR i : INTEGER;
  584.       ch: CHAR;
  585. BEGIN
  586.   i := 0;
  587.   LOOP
  588.     ch := text^[i];
  589.     IF ch = 0C THEN EXIT END;
  590.     IF (ch >= "A") & (ch <= "Z")
  591.     THEN
  592.       ch := CHR(ORD('A')+ORD('Z')-ORD(ch));
  593.     END;
  594.     IF (ch >= "a") & (ch <= "z")
  595.     THEN
  596.       ch := CHR(ORD('a')+ORD('z')-ORD(ch));
  597.     END;
  598.     text^[i] := ch;
  599.     INC(i);
  600.   END;
  601. END Mirror;
  602.  
  603. PROCEDURE Rot18 (text : textPtr);
  604.   VAR i : INTEGER;
  605.       p : INTEGER;
  606.       ch: CHAR;
  607.       table : ARRAY [0..62] OF CHAR;
  608. BEGIN
  609.   i := 0;
  610.   table := "STUVWXYZ0123456789ABCDEFGHIJKLMNOPQRnopqrstuvwxyzabcdefghijklm";
  611.   (* Erst mal radikal grožwandeln *)
  612.   LOOP
  613.     ch := text^[i];
  614.     IF ch = 0C THEN EXIT END;
  615.     p := Strings.Pos(ch, "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz", 0);
  616.     IF p >= 0
  617.     THEN
  618.       text^[i] := table[p];
  619.     END;
  620.     INC(i);
  621.   END;
  622. END Rot18;
  623.  
  624. PROCEDURE RotXX (text : textPtr);
  625.   VAR i : INTEGER;
  626.       ch: CHAR;
  627. BEGIN
  628.   i := 0;
  629.   (* Erst mal radikal grožwandeln *)
  630.   LOOP
  631.     ch := text^[i];
  632.     IF ch = 0C THEN EXIT END;
  633.     IF (ch >= "A") & (ch <= "Z")
  634.     THEN
  635.       text^[i] := CHR( (((ORD(ch) - ORD('A')) + rotateFaktor) MOD 26) + ORD ('A'));
  636.     END;
  637.     IF (ch >= "a") & (ch <= "z")
  638.     THEN
  639.       text^[i] := CHR( (((ORD(ch) - ORD('a')) + rotateFaktor) MOD 26) + ORD ('a'));
  640.     END;
  641.     INC(i);
  642.   END;
  643. END RotXX;
  644.  
  645. PROCEDURE Protect (text : textPtr);
  646.   VAR l : CARDINAL;
  647. BEGIN
  648.   l := (*SYSTEM.*)LENGTH (text^);
  649.   WHILE (l > 0) & ((text^[l-1] = CR) OR (text^[l-1] = LF)) DO DEC (l) END;
  650.   text^[l] := CR;
  651.   text^[l+1] := LF;
  652.   text^[l+2] := 0C;
  653. END Protect;
  654.  
  655. PROCEDURE XXDecode (text: textPtr);
  656.   VAR l : CARDINAL;
  657.       saveCh : CHAR;
  658. BEGIN
  659.   l := (*SYSTEM.*)LENGTH (text^);
  660.   WHILE (l > 0) & ((text^[l-1] = CR) OR (text^[l-1] = LF)) DO DEC (l) END;
  661.   saveCh := text^[l];
  662.   text^[l] := 0C;
  663.   v.bool := UUDecode.DecodeLine (text^);
  664.   text^[l] := saveCh;
  665. END XXDecode;
  666.  
  667. PROCEDURE TransformBlock (ed : EDITPTR; trans : formFunc; wholeLines : BOOLEAN);
  668.   VAR ch2       : POINTER TO CHAR;
  669.       save2     : CHAR;
  670.       text, t1  : textPtr;
  671.       le        : INTEGER;
  672.       l         : LONGINT;
  673.       frame     : Rectangle;
  674.       blS, blE  : aMark;
  675.       oldCurrLine: LONGINT;
  676.       oldRow    : INTEGER;
  677. BEGIN
  678.   (* Ruft fr jede Zeile im Block die Funktion trans auf 
  679.    * Anfang und Ende werden entsprechend umgeformt!
  680.    *)
  681.   WITH ed^ DO
  682.     oldCurrLine := currLineNr;
  683.     oldRow := currRow;
  684.     ShowFileChanged (ed);
  685.     IF wholeLines THEN
  686.       blS := blocks[0].blockStart;
  687.       blE := blocks[0].blockEnd;
  688.       blocks[0].blockStart.row := 0;
  689.       IF blocks[0].blockEnd.line = totalLineNr - 1
  690.       THEN
  691.         blocks[0].blockEnd.row := ToLineEnd (ed, blocks[0].blockEnd.line);
  692.       ELSE
  693.         blocks[0].blockEnd.row := 0;
  694.         INC (blocks[0].blockEnd.line);
  695.       END;
  696.     END;
  697.     SaveOp (ed, blockPaste, FALSE); 
  698.     SetCurrLine (ed, blocks[0].blockStart.line);
  699.     currRow := blocks[0].blockStart.row;
  700.     EditGlobals.FixCursorPos (ed);
  701.     IF blocks[0].blockStart.line = blocks[0].blockEnd.line 
  702.     THEN
  703.       IF ~wholeLines THEN
  704.         (* Nur Block in einer Zeile *)
  705.         t1 := ADR (editLine.text^[blocks[0].blockStart.row]);
  706.         ch2 := ADR (editLine.text^[blocks[0].blockEnd.row]);
  707.         save2 := ch2^;
  708.         ch2^ := 0C;
  709.       ELSE
  710.         t1 := editLine.text;
  711.       END;
  712.       trans (t1);
  713.       IF ~wholeLines THEN
  714.         ch2^ := save2;
  715.       END;
  716.       editChanged := TRUE;
  717.       editLen := (*SYSTEM.*)LENGTH (editLine.text^);
  718.       v.bool := EditBase.PutCurrLine (ed);
  719.     ELSE
  720.       (* mehrzeiliger Block *)
  721.       l := blocks[0].blockStart.line;
  722.       WHILE l <= blocks[0].blockEnd.line DO
  723.         le := editLen;
  724.         IF wholeLines THEN AllocNew (editLine, editLen + 3) END;
  725.         WITH editLine DO
  726.           IF (l = blocks[0].blockStart.line) & (blocks[0].blockStart.row > 0) & ~wholeLines THEN
  727.             (* Nur Teilweise bearbeiten *)
  728.             t1 := ADR (text^[blocks[0].blockStart.row]);
  729.             trans (t1);
  730.           ELSIF (l = blocks[0].blockEnd.line) & (blocks[0].blockEnd.row < le) & ~wholeLines  THEN
  731.             (* ebenfalls nur teilweise bearbeiten *)
  732.             ch2 := ADR (text^[blocks[0].blockEnd.row]);
  733.             save2 := ch2^;
  734.             ch2^ := 0C;
  735.             trans (text);
  736.             ch2^ := save2;
  737.           ELSE
  738.             trans (text);
  739.           END;
  740.         END (* WITH editLine *);
  741.         editChanged := TRUE;
  742.         editLen := (*SYSTEM.*)LENGTH (editLine.text^);
  743.         SetCurrLine (ed, currLineNr + 1);
  744.         INC (l);
  745.       END (* WHILE *);
  746.     END; (* IF blockStart.line = blockEnd.line *)
  747.     (* Noch Blockstart fr Undobuffer merken *)
  748.     NewBlockToUndoBuffer (ed);
  749.     IF wholeLines
  750.     THEN
  751.       blocks[0].blockStart := blS;
  752.       blocks[0].blockEnd := blE;
  753.     END;
  754.     currRow := oldRow;
  755.     SetCurrLine (ed, oldCurrLine);
  756.     (* Jetzt noch redraw von blockstart bis blockende *)
  757.     redrawLineArea (ed, blocks[0].blockStart.line, blocks[0].blockEnd.line);
  758.   END; 
  759. END TransformBlock;
  760.  
  761. PROCEDURE Home (ed : EDITPTR; ende : BOOLEAN); 
  762.   VAR newLine : LONGINT;
  763.       dir     : INTEGER;
  764. BEGIN
  765.   WITH ed^ DO
  766.     HideMouse(); 
  767.     HideCursor (ed);
  768.     IF block & ~readOnly THEN ClearBlock (ed); END;
  769.     IF ende THEN
  770.       newLine := BinOps.HigherLInt(0, totalLineNr - LONG(windLines));
  771.       IF (newLine # StartLine) & (newLine # 0) THEN
  772.         SetStartLine (ed, newLine, TRUE);
  773.       END;
  774.       SetCurrLine (ed, totalLineNr-1);
  775.       currRow := editLen;
  776.       EditGlobals.FixCursorPos (ed);
  777.     ELSE (* IF Ende *)
  778.       IF StartLine # 0 THEN
  779.         SetStartLine (ed, 0, TRUE);
  780.       END;
  781.       SetCurrLine (ed, 0);
  782.       currRow := 0;
  783.     END;
  784.     ShowCursor(ed);
  785.     ShowMouse (FALSE);
  786.   END (* WITH ed^ DO *);
  787. END Home;
  788.  
  789. PROCEDURE SwapLines (ed : EDITPTR; withUp : BOOLEAN);
  790.   VAR l : LONGINT;
  791.       swap : aLineDesc;
  792.       len  : INTEGER;
  793. BEGIN
  794.   WITH ed^ DO
  795.     IF block THEN RETURN END;
  796.     IF withUp THEN
  797.       l := currLineNr-1;
  798.     ELSE
  799.       l := currLineNr+1;
  800.     END;
  801.     IF (l < 0) OR (l >= totalLineNr) THEN RETURN END;
  802.     ShowFileChanged (ed);
  803.     HideMouse ();
  804.     HideCursor (ed);
  805.     v.bool := EditBase.GetLineLength (ed, l, len);
  806.     ALLOCATE (swap.text, len+2);
  807.     IF swap.text = NIL THEN RETURN END;
  808.     v.bool := EditBase.GetLine (ed, l, swap.text^, len);
  809.     IF len > editLen THEN 
  810.       v.bool := EditBase.PutLine (ed, l, editLine.text^, editLen);
  811.       v.bool := EditBase.PutLine (ed, currLineNr, swap.text^, len);
  812.     ELSE
  813.       v.bool := EditBase.PutLine (ed, currLineNr, swap.text^, len);
  814.       v.bool := EditBase.PutLine (ed, l, editLine.text^, editLen);
  815.     END;
  816.     editChanged := FALSE;
  817.     drawLine (ed, SHORT(currLineNr-StartLine));
  818.     IF withUp THEN
  819.       drawLine (ed, SHORT(currLineNr-StartLine)-1);
  820.       SetCurrLine (ed, currLineNr-1);
  821.     ELSE
  822.       drawLine (ed, SHORT(currLineNr-StartLine)+1);
  823.       SetCurrLine (ed, currLineNr+1);
  824.     END;
  825.     DEALLOCATE (swap.text, 0);
  826.     CenterCurrline (ed);
  827.     ShowCursor (ed);
  828.     ShowMouse (FALSE);
  829.   END (* WITH ed^ DO *)
  830. END SwapLines;
  831.  
  832.                 (* IO-Routinen *)
  833.  
  834.                 (* allgemeine Saveroutine *)
  835.                 
  836. VAR buffer : POINTER TO ARRAY [$0L..$1FFFFL] OF CHAR;
  837.     bufPos, bufSize : LONGCARD;
  838.  
  839.   PROCEDURE WriteBuffered (fHdl : INTEGER; VAR l : LONGCARD; buf : ADDRESS);
  840.     VAR (*$Reg*) remain  : LONGCARD;
  841.         (*$Reg*) wrBytes : LONGCARD;
  842.         (*$Reg*) ptr     : POINTER TO ARRAY [0..$FFFFFFFF] OF CHAR;
  843.   BEGIN
  844.     IF l+bufPos > bufSize
  845.     THEN
  846.       remain := l-(bufSize-bufPos);
  847.       Block.Copy (buf, bufSize-bufPos, ADR(buffer^[bufPos]));
  848.       INC(bufPos, bufSize-bufPos);
  849.       wrBytes := bufPos;
  850.       MagicDOS.Fwrite (fHdl, bufPos, buffer);
  851.       IF bufPos # wrBytes
  852.       THEN
  853.         l := bufPos;
  854.         RETURN
  855.       END;
  856.       ptr := buf;
  857.       Block.Copy (ADR(ptr^[l-remain]), remain, buffer);
  858.       bufPos := remain;
  859.     ELSE
  860.       Block.Copy (buf, l, ADR(buffer^[bufPos]));
  861.       INC(bufPos,l);
  862.     END;
  863.   END WriteBuffered;
  864.   
  865.   PROCEDURE WritePrinter (fHdl : INTEGER; VAR l : LONGCARD; buf : ADDRESS);
  866.     VAR str : textPtr;
  867.   BEGIN
  868.     IF l > bufSize
  869.     THEN
  870.       str := textPtr (buf);
  871.       IF str^[0] = CR
  872.       THEN
  873.         IF Printer.Response = Printer.done THEN Printer.WriteLn(); END;
  874.       ELSE
  875.         IF Printer.Response = Printer.done THEN Printer.WriteString (str^); END;
  876.       END;
  877.     ELSE
  878.       Block.Copy (buf, l, buffer);
  879.       str := textPtr (buffer);
  880.       str^[SHORT(l)] := 0C;
  881.       IF (l>0) & (str^[SHORT(l)-1] = CR) THEN str^[SHORT(l)-1] := 0C END;
  882.       IF str^[0] = CR
  883.       THEN
  884.         IF Printer.Response = Printer.done THEN Printer.WriteLn(); END;
  885.       ELSE
  886.         IF Printer.Response = Printer.done THEN Printer.WriteString (str^); END;
  887.       END;
  888.     END;
  889.   END WritePrinter;
  890.  
  891. PROCEDURE outputText (ed : EDITPTR; fromLine : LONGINT; fromRow : INTEGER;
  892.                       toLine : LONGINT; toRow : INTEGER; fHdl : INTEGER; umbruch : BOOLEAN;
  893.                       usePrintMod : BOOLEAN) : BOOLEAN;
  894.   CONST CrLf = 15C+12C+0C;
  895.         Cr   = 15C+0C;
  896.         Lf   = 12C+0C;
  897.  
  898.   VAR line : LONGINT;
  899.       saveall : BOOLEAN;
  900.       i    : LONGINT;
  901.       wlen : LONGCARD;
  902.       len  : LONGCARD;
  903.       length   : INTEGER;
  904.       writeAdr : textPtr;
  905.       writeProc : PROCEDURE (INTEGER, VAR LONGCARD, ADDRESS);
  906.       chPtr : POINTER TO CHAR;
  907.       writeCR : BOOLEAN;
  908.       writeLF : BOOLEAN;
  909.       text    : textPtr;
  910.       buff    : aBufferPtr;
  911.       s       : ARRAY [0..255] OF CHAR;
  912.       margin  : INTEGER;
  913.       marginStr : ARRAY [0..12] OF CHAR;
  914.  
  915. BEGIN
  916.   MouseBusy();
  917.   saveall := toLine < fromLine;
  918.   buffer := NIL;
  919.   bufSize := $F000;
  920.   WHILE buffer = NIL DO
  921.     ALLOCATE (buffer, bufSize);
  922.     IF buffer = NIL THEN DEC(bufSize, $100) END;
  923.   END;
  924.   IF bufSize = 0
  925.   THEN
  926.     writeProc := MagicDOS.Fwrite;
  927.   ELSE
  928.     IF usePrintMod 
  929.     THEN
  930.       writeProc := WritePrinter;
  931.       ConfVars.GetConfDefInt (cPrtMargin, margin, 0);
  932.       IF margin > 0 THEN
  933.         Strings.Assign (Strings.Space (margin), marginStr, v.bool);
  934.       END;
  935.     ELSE
  936.       writeProc := WriteBuffered;
  937.     END;
  938.   END;
  939.   bufPos := 0;
  940.   IF saveall & ~(usePrintMod OR ed^.readOnly)
  941.   THEN
  942.     WITH ed^ DO
  943.       buff := firstBuff;
  944.       WHILE buff # NIL DO
  945.         len := buff^.usedMem;
  946.         writeProc (fHdl, len, buff^.buffer);
  947.         IF len # LONGCARD(LONG(buff^.usedMem))
  948.         THEN
  949.           (* Schreibfehler! *)
  950.           MouseArrow();
  951.           MTE.info (MTE.NoWrite);
  952.           RETURN FALSE;
  953.         END;
  954.         buff := buff^.next;
  955.       END;
  956.     END;
  957.   ELSE
  958.   (* Nur langsames, zeilenweises sichern *)
  959.     IF saveall & (usePrintMod OR ed^.readOnly)
  960.     THEN 
  961.       fromLine := 0; fromRow := 0;
  962.       toLine := ed^.totalLineNr - 1;
  963.       v.bool := EditBase.GetLineLength (ed, toLine, toRow);
  964.       (* Extinfo ausgeben, falls vorhanden *)
  965.       IF ed^.readOnly & ~usePrintMod & 
  966.          (ADDRESS(ed^.userPrint) # NIL)
  967.        & ed^.userPrint (ed^.wdw, LFIRST, s)
  968.       THEN
  969.         (* erste Zeile ausgeben *)
  970.         writeAdr := ADR(s);
  971.         REPEAT
  972.           len := LONG(LENGTH(s));
  973.           wlen := len;
  974.           writeProc (fHdl, wlen, writeAdr);
  975.           IF wlen # len
  976.           THEN
  977.             (* Schreibfehler! *)
  978.             MouseArrow();
  979.             MTE.info (MTE.NoWrite);
  980.             RETURN FALSE;
  981.           END;
  982.           (* CR/LF schreiben *)
  983.           wlen := 2;
  984.           writeProc (fHdl, wlen, CADR(CrLf));
  985.           IF wlen # 2 
  986.           THEN
  987.             MouseArrow ();
  988.             MTE.info (MTE.NoWrite);
  989.             RETURN FALSE
  990.           END;
  991.         UNTIL ~ed^.userPrint (ed^.wdw, LNEXT, s);
  992.       END;
  993.     END;
  994.     line := fromLine;
  995.     i := fromLine;
  996.     WHILE line <= toLine DO
  997.       v.bool := EditBase.GetLineAdr (ed, line, writeAdr, length);
  998.       len := VAL (LONGCARD, length);
  999.       IF i = fromLine
  1000.       THEN
  1001.         INC (writeAdr, fromRow);
  1002.         len := LONGCARD(BinOps.HigherLInt ( 0, LONGINT(len)-LONG(fromRow)));
  1003.       END;
  1004.       IF i = toLine
  1005.       THEN
  1006.         DEC (len, length - toRow);
  1007.       END;
  1008.       (* CR/LFs am Zeilenende entfernen *)
  1009.       writeLF := FALSE;
  1010.       writeCR := FALSE;
  1011.       WHILE (len > 0) & ((writeAdr^[SHORT(len-1)]=CR) OR (writeAdr^[SHORT(len-1)]=LF)) DO
  1012.         IF writeAdr^[SHORT(len-1)]=LF THEN writeLF := TRUE END;
  1013.         IF writeAdr^[SHORT(len-1)]=CR THEN writeCR := TRUE END;
  1014.         DEC (len);
  1015.       END;
  1016.       IF ed^.readOnly
  1017.       THEN
  1018.         writeLF := TRUE;
  1019.         writeCR := TRUE;
  1020.       END;
  1021.       IF (i>= fromLine) & (i <= toLine)
  1022.       THEN
  1023.         IF usePrintMod & (margin > 0) THEN 
  1024.           IF Printer.Response = Printer.done THEN Printer.WriteString (marginStr); END;
  1025.         END;
  1026.         wlen := len;
  1027.         writeProc (fHdl, wlen, writeAdr);
  1028.         IF wlen # len
  1029.         THEN
  1030.           (* Schreibfehler! *)
  1031.           MouseArrow();
  1032.           MTE.info (MTE.NoWrite);
  1033.           RETURN FALSE;
  1034.         END;
  1035.       END;
  1036.       IF (i >= fromLine) & (i <= toLine)
  1037.       THEN
  1038.         IF (writeLF & writeCR)
  1039.         THEN
  1040.           len := 2;
  1041.           writeAdr := CADR (CrLf);
  1042.         ELSIF writeLF
  1043.         THEN
  1044.           len := 1;
  1045.           writeAdr := CADR (Lf);
  1046.         ELSIF (writeCR & ~umbruch) OR (writeCR & usePrintMod)
  1047.         THEN
  1048.           len := 1;
  1049.           writeAdr := CADR (Cr);
  1050.         ELSE
  1051.           len := 0;
  1052.         END;
  1053.         IF usePrintMod
  1054.         THEN
  1055.           IF Printer.Response = Printer.done THEN Printer.WriteLn() END;
  1056.         ELSIF ~((i = toLine) & (toRow # length)) & (len > 0)
  1057.         THEN
  1058.           wlen := len;
  1059.           writeProc (fHdl, len, writeAdr);
  1060.           IF len # wlen
  1061.           THEN
  1062.             (* Schreibfehler! *)
  1063.             MouseArrow();
  1064.             MTE.info (MTE.NoWrite);
  1065.             RETURN FALSE;
  1066.           END;
  1067.         END;
  1068.       END; 
  1069.       INC (line);
  1070.       INC(i);
  1071.     END; (* WHILE line <= toLine *)
  1072.   END;
  1073.   IF (bufSize > 0) & (bufPos > 0)
  1074.   THEN
  1075.     IF ~usePrintMod
  1076.     THEN
  1077.       (* Buffer noch flushen *)
  1078.       wlen := bufPos;
  1079.       MagicDOS.Fwrite (fHdl, bufPos, buffer);
  1080.     END;
  1081.     IF (wlen # bufPos) & ~usePrintMod
  1082.     THEN
  1083.       MouseArrow();
  1084.       MTE.info (MTE.NoWrite);    
  1085.       RETURN FALSE;
  1086.     END;
  1087.   END;
  1088.   IF bufSize > 0
  1089.   THEN
  1090.     DEALLOCATE (buffer, 0);
  1091.   END;
  1092.   MouseArrow();
  1093.   RETURN TRUE;
  1094. END outputText;
  1095.  
  1096. PROCEDURE KillEditor (VAR ed : EDITPTR);
  1097.   VAR line : aLinePtr;
  1098.       edi  : EDITPTR;
  1099. BEGIN
  1100.   WITH ed^ DO
  1101.     WHILE firstBuff # NIL DO
  1102.       currentBuff := firstBuff;
  1103.       EditBase.FreeBuffer (ed);
  1104.     END;
  1105.     DEALLOCATE (editLine.text, 0);
  1106.     IF fileName.text # NIL THEN DEALLOCATE (fileName.text, 0); END;
  1107.   END; (* WITH ed *)
  1108.   IF editList # ed
  1109.   THEN
  1110.     edi := editList; 
  1111.     WHILE edi^.nextEdit # ed DO
  1112.       (* ed suchen in Liste *)
  1113.       edi := edi^.nextEdit;
  1114.     END;
  1115.     edi^.nextEdit := ed^.nextEdit;
  1116.   ELSE
  1117.     editList := ed^.nextEdit
  1118.   END;
  1119.   DISPOSE (ed);
  1120.   IF editList = NIL
  1121.   THEN
  1122.     (* letzter Editor geschlossen *)
  1123.     FreeUndoBuffer();
  1124.   END;
  1125. END KillEditor;
  1126.  
  1127. PROCEDURE CreateEditor(VAR ed : EDITPTR) : BOOLEAN;
  1128.   VAR currEd : EDITPTR;
  1129.       found  : BOOLEAN;
  1130. BEGIN
  1131.   found := FALSE;
  1132.   NEW (ed);
  1133.   IF ed = NIL THEN RETURN FALSE END;
  1134.   IF editList = NIL
  1135.   THEN 
  1136.     (* noch kein Editor da! *)
  1137.     editList := ed;
  1138.     ed^.nextEdit := NIL;
  1139.   ELSE
  1140.     currEd := editList;
  1141.     WHILE (currEd # NIL) & ~found DO
  1142.       IF currEd^.nextEdit = NIL
  1143.       THEN 
  1144.         found := TRUE
  1145.       ELSE
  1146.         currEd := currEd^.nextEdit;
  1147.       END;
  1148.     END;
  1149.     IF found THEN
  1150.       currEd^.nextEdit := ed;
  1151.       WITH ed^ DO
  1152.         currentBuff := NIL;
  1153.         firstBuff := NIL;
  1154.       END;
  1155.     ELSE
  1156.       DISPOSE (ed);
  1157.       ed := NIL;
  1158.       RETURN FALSE
  1159.     END;
  1160.   END;
  1161.   WITH ed^ DO
  1162.     wdw := -1;
  1163.     StartLine := 0;
  1164.     currLineNr := 0;
  1165.     totalLineNr := 1;
  1166.     tabSize := 4;
  1167.     currRow := 0;
  1168.     currentBuff := NIL;
  1169.     editLine.text := NIL;
  1170.     ALLOCATE (editLine.text, 16);
  1171.     IF editLine.text = NIL THEN RETURN FALSE END;
  1172.     editLine.length := 16;
  1173.     editLine.text^[0] := "";
  1174.     firstBuff := NIL;
  1175.     multiBlockMark := FALSE;
  1176.     multiBlockIdx := -1;
  1177.     editChanged := FALSE;
  1178.     editLen := 0;
  1179.     nextEdit := NIL;
  1180.     parseEffects := FALSE;
  1181.     userDD := FALSE;
  1182.     isEnriched := FALSE;
  1183.   END;
  1184.   RETURN TRUE
  1185. END CreateEditor;
  1186.  
  1187. PROCEDURE ReadBuffer (VAR ed : EDITPTR; VAR buf: ADDRESS; len : LONGCARD; 
  1188.                       freeBuffer: BOOLEAN; VAR err: ErrReason) : BOOLEAN;
  1189.   VAR allocSize : INTEGER;
  1190.       chkLen,
  1191.       i         : INTEGER;  
  1192.       ptr       : textPtr;
  1193.       isText    : BOOLEAN;
  1194.       ch        : CHAR;
  1195. BEGIN
  1196.   WITH ed^ DO
  1197.   (*
  1198.     (* Erstmal den Buffer prfen *)
  1199.     IF len > 100
  1200.     THEN
  1201.       chkLen := 100;
  1202.     ELSE
  1203.       chkLen := VAL (INTEGER,len);
  1204.     END;
  1205.     ptr := buf;
  1206.     i := 0;
  1207.     isText := TRUE;
  1208.     WHILE (i < chkLen) & isText DO
  1209.       ch := ptr^[i];
  1210.       IF (ORD (ch) < 32) & 
  1211.          ~(ch IN CharSet{0c, TAB, CR, LF, 20C, 21C, 25C, 32C})
  1212.       THEN
  1213.         isText := FALSE;
  1214.       END;
  1215.       INC (i);
  1216.     END;
  1217.     IF ~isText
  1218.     THEN
  1219.       MouseArrow();
  1220.       MTE.info (noTextErr);
  1221.       err := noTextError;
  1222.       RETURN FALSE
  1223.     END;
  1224.     *)
  1225.     err := memError;
  1226.     IF firstBuff = NIL
  1227.     THEN 
  1228.       IF readOnly & (len + 50 < EditBase.memBlockSize)
  1229.       THEN
  1230.         allocSize := INTEGER(SHORT(len) + 50);
  1231.       ELSE
  1232.         allocSize := EditBase.memBlockSize
  1233.       END;
  1234.       IF ~EditBase.GetBuffer (ed, allocSize)
  1235.       THEN RETURN FALSE END;
  1236.       currentBuff := firstBuff;
  1237.       WITH currentBuff^ DO
  1238.         fromLine := 0;
  1239.         toLine := 0;
  1240.         usedMem := 0;
  1241.       END;
  1242.       currLineNr := 0;
  1243.       currRow := 0;
  1244.       totalLineNr := 1;
  1245.     END;
  1246.     IF editChanged THEN v.bool := EditBase.PutCurrLine (ed); END;
  1247.     IF EditBase.InsertBuffer (ed, buf, len, freeBuffer)
  1248.     THEN
  1249.       UpdateCurrLine (ed, currLineNr);
  1250.       RETURN TRUE
  1251.     ELSE
  1252.       RETURN FALSE
  1253.     END;
  1254.   END;
  1255. END ReadBuffer;
  1256.  
  1257. PROCEDURE readText (VAR ed : EDITPTR; fastRead : BOOLEAN;
  1258.                     flen : LONGCARD; VAR fHdl : INTEGER;
  1259.                     right : INTEGER; VAR readBuf : ADDRESS; 
  1260.                     inLine : BOOLEAN; fullText : BOOLEAN) : BOOLEAN;
  1261.   CONST smallBufSize = 28000L;
  1262.  
  1263.   VAR readBytes : LONGCARD;
  1264.       tmpEd     : EDITPTR;
  1265.       cLine     : LONGINT;
  1266.       clLine    : LONGINT;
  1267.       cRow      : INTEGER;
  1268.       i,
  1269.       spaces    : INTEGER;
  1270.       err       : ErrReason;
  1271.       bufPos    : LONGCARD;
  1272.       rb        : LONGCARD;
  1273.       wasBlock  : BOOLEAN;
  1274.       bEnd      : aMark;
  1275.       text      : textPtr;
  1276.       ch        : CHAR;
  1277.  
  1278. PROCEDURE CheckMM2Format ();
  1279. BEGIN
  1280.   WITH ed^ DO
  1281.     IF fullText
  1282.     THEN
  1283.       WITH ed^ DO
  1284.         (* Position sichern *)
  1285.         clLine := currLineNr;
  1286.         cRow := currRow;
  1287.         (* Anpassung an MM2-Kurzformat *)
  1288.         cLine := 0;
  1289.         SetCurrLine (ed, cLine);
  1290.         (* Erstmal prfen, ob berhaupt was gewandelt werden muž! *)
  1291.         IF editLine.text^[0] = 20C
  1292.         THEN
  1293.           (* Ok, ist MM2-Kurzformat, wandeln *)
  1294.           WHILE cLine < ed^.totalLineNr DO
  1295.             SetCurrLine (ed, cLine);
  1296.             IF (editLen > 1) & (editLine.text^[0] = 20C) & (ORD(editLine.text^[1]) >= 32)
  1297.             THEN
  1298.               (* change line *)
  1299.               spaces := BinOps.HigherInt (0, ORD (editLine.text^[1]) - 32);
  1300.               AllocNew (editLine, editLen  + spaces + 2);
  1301.               Strings.Delete (editLine.text^, 0, 2, v.bool);
  1302.               IF (spaces > 0) & (spaces < 80) THEN 
  1303.                 Strings.Insert (Strings.Space (spaces), 0, editLine.text^, v.bool);
  1304.               END;
  1305.               (* Zeilenende anpassen *)
  1306.               editLen := editLen + spaces - 2;
  1307.               i := editLen;
  1308.               WHILE editLine.text^[i] # 0C DO INC (i) END;
  1309.               DEC (i);
  1310.               WHILE (i >= 0) & ((editLine.text^[i] = CR) OR (editLine.text^[i] = LF)) DO DEC (i) END;
  1311.               INC (i);
  1312.               editLine.text^[i] := CR;
  1313.               editLine.text^[i+1] := LF;
  1314.               editLine.text^[i+2] := 0C;
  1315.               editLen := LENGTH (editLine.text^);
  1316.               editChanged := TRUE;
  1317.             END;
  1318.             INC (cLine);
  1319.           END;
  1320.         END;
  1321.         (* Position restaurieren *)
  1322.         SetCurrLine (ed, clLine);
  1323.         currRow := cRow;
  1324.       END;
  1325.     END;
  1326.   END;
  1327. END CheckMM2Format;
  1328.  
  1329. BEGIN
  1330.   IF fastRead THEN
  1331.     readBytes := flen;
  1332.     MagicDOS.Fread (fHdl, readBytes, readBuf);
  1333.     IF readBytes # flen THEN
  1334.       (* nicht alles gelesen! *)
  1335.       IF SHORT(LONGINT(readBytes)) = -37
  1336.       THEN
  1337.         CatFiles.ErrorAlert (-37)
  1338.       ELSE
  1339.         v.int := mtAlerts.Alert (1, readErr);
  1340.       END;
  1341.       v.int := MagicDOS.Fclose (fHdl);
  1342.       RETURN FALSE;
  1343.     END;
  1344.     v.int := MagicDOS.Fclose (fHdl);
  1345.     CatFiles.ErrorAlert (v.int);
  1346.     v.bool := EditBase.PutCurrLine (ed);
  1347.     fHdl := 0;
  1348.     (* Text aus Buffer in Editor Zeilenweise bertragen *)
  1349.     HideCursor (ed);
  1350.     MouseBusy();
  1351.     ed^.rightMargin := right;
  1352.     (*
  1353.     IF ~fullText 
  1354.     THEN
  1355.       IF ~EditBase.InsertBuffer (ed, readBuf, flen)
  1356.       THEN
  1357.         IF readBuf # NIL THEN DEALLOCATE (readBuf, 0); END;
  1358.         HideMouse();
  1359.         ShowCursor (ed);
  1360.         MouseArrow();
  1361.         RETURN FALSE
  1362.       END;
  1363.         
  1364.     ELSE
  1365.     *)
  1366.       IF ~ReadBuffer (ed, readBuf, flen, TRUE, err)
  1367.       THEN
  1368.         IF readBuf # NIL THEN DEALLOCATE (readBuf, 0); END;
  1369.         HideMouse();
  1370.         ShowCursor (ed);
  1371.         ShowMouse (FALSE); 
  1372.         MouseArrow();
  1373.         CASE err OF
  1374.           memError : OutOfMem(); |
  1375.           readError: (* schon behandelt, tritt nicht auf *) |
  1376.           noTextError : (* Fehlermeldung kam schon *) |
  1377.         ELSE
  1378.         END;
  1379.         RETURN FALSE
  1380.       END;
  1381. (*    END; *)
  1382.     (* 2 Buffer wieder freigeben *)
  1383.     IF readBuf # NIL THEN DEALLOCATE (readBuf, 0); END;
  1384.     CheckMM2Format();
  1385.     SetDocument (ed);
  1386.     HideMouse();
  1387.     ShowCursor (ed);
  1388.     ShowMouse (FALSE); 
  1389.     MouseArrow();
  1390.   ELSE
  1391.     (* langsames Lesen des Textes *)
  1392.     IF readBuf # NIL THEN DEALLOCATE (readBuf,0); END;
  1393.     ALLOCATE (readBuf, smallBufSize);
  1394.     IF readBuf = NIL
  1395.     THEN
  1396.       OutOfMem();
  1397.       RETURN FALSE;
  1398.     END;
  1399.     v.bool := EditBase.PutCurrLine (ed);
  1400.     (* Text aus Buffer in Editor Zeilenweise bertragen *)
  1401.     HideCursor (ed);
  1402.     MouseBusy();
  1403.     WITH ed^ DO
  1404.       rightMargin := right;
  1405.       bufPos := 0;
  1406.       clLine := currLineNr;
  1407.       cRow := currRow;
  1408.       wasBlock := block;
  1409.       bEnd := blocks[0].blockEnd;
  1410.       block := TRUE;
  1411.       WHILE bufPos < flen DO
  1412.         v.lcard := MagicDOS.Fseek (bufPos, fHdl, MagicDOS.SeekStart);
  1413.         readBytes := BinOps.LowerLCard (flen - bufPos, smallBufSize);
  1414.         rb := readBytes;
  1415.         MagicDOS.Fread (fHdl, readBytes, readBuf);
  1416.         IF readBytes # rb THEN
  1417.           (* nicht alles gelesen! *)
  1418.           IF INT(readBytes) = -37
  1419.           THEN
  1420.             CatFiles.ErrorAlert (-37)
  1421.           ELSE
  1422.             v.int := mtAlerts.Alert (1, readErr);
  1423.           END;
  1424.           v.int := MagicDOS.Fclose (fHdl);
  1425.           RETURN FALSE;
  1426.         END;
  1427.         (* Jetzt ausgehend vom Ende des Buffers ein Zeilenende suchen 
  1428.          * und nur bis dahin einlesen
  1429.          *)
  1430.         IF bufPos + readBytes < flen 
  1431.         THEN
  1432.           text := readBuf;
  1433.           ch := text^[SHORT(readBytes)-1];
  1434.           WHILE (ch # CR) & (ch # LF) & (readBytes > 0) DO
  1435.              DEC (readBytes); 
  1436.              ch := text^[SHORT(readBytes)-1];
  1437.           END;
  1438.         END;
  1439.         IF ~ReadBuffer (ed, readBuf, readBytes, FALSE, err)
  1440.         THEN
  1441.           IF readBuf # NIL THEN DEALLOCATE (readBuf, 0); END;
  1442.           HideMouse();
  1443.           ShowCursor (ed);
  1444.           ShowMouse (FALSE); 
  1445.           MouseArrow();
  1446.           CASE err OF
  1447.             memError : OutOfMem(); |
  1448.             readError: (* schon behandelt, tritt nicht auf *) |
  1449.             noTextError : (* Fehlermeldung kam schon *) |
  1450.           ELSE
  1451.           END;
  1452.           v.int := MagicDOS.Fclose (fHdl);
  1453.           CatFiles.ErrorAlert (v.int);
  1454.           RETURN FALSE
  1455.         END;
  1456.         IF blocks[0].blockEnd.line > totalLineNr - 1
  1457.         THEN
  1458.           blocks[0].blockEnd.line := totalLineNr - 1;
  1459.           v.bool := EditBase.GetLineLength (ed, blocks[0].blockEnd.line, blocks[0].blockEnd.row);
  1460.         END;
  1461.         SetCurrLine (ed, blocks[0].blockEnd.line);
  1462.         currRow := blocks[0].blockEnd.row;
  1463.         INC (bufPos, readBytes);
  1464.       END;
  1465.       v.int := MagicDOS.Fclose (fHdl);
  1466.       CatFiles.ErrorAlert (v.int);
  1467.       DEALLOCATE (readBuf, 0);
  1468.       (* Position restaurieren *)
  1469.       block := wasBlock;
  1470.       blocks[0].blockEnd := bEnd;
  1471.       SetCurrLine (ed, clLine);
  1472.       currRow := cRow;
  1473.     END;
  1474.     CheckMM2Format();
  1475.     SetDocument (ed);
  1476.     HideMouse();
  1477.     ShowCursor (ed);
  1478.     ShowMouse (FALSE); 
  1479.     MouseArrow();
  1480.   END; (* IF fastRead *)
  1481.   RETURN TRUE
  1482. END readText;
  1483.  
  1484. PROCEDURE Goto (ed : EDITPTR; line : LONGINT; row : INTEGER);
  1485. BEGIN
  1486.   IF line-1 >= 0
  1487.   THEN
  1488.     HideMouse();
  1489.     HideCursor (ed);
  1490.     SetCurrLine (ed, line-1);
  1491.     ed^.currRow := BinOps.LowerInt (row, ed^.editLen);
  1492.     EditGlobals.FixCursorPos (ed);
  1493.     CenterCurrline (ed);
  1494.     ShowCursor (ed);
  1495.     ShowMouse (FALSE);
  1496.   END;
  1497. END Goto;
  1498.  
  1499. PROCEDURE showError (ed : EDITPTR);
  1500.  VAR adr : RECORD a,b : ADDRESS; END;
  1501. BEGIN
  1502.   WITH ed^ DO
  1503.     IF errLine >= 0 THEN
  1504.       HideMouse();
  1505.       HideCursor(ed);
  1506.       ClearBlock (ed);
  1507.       Goto (ed, errLine, errRow);
  1508.       WdwManager.SetWdwInfoline (wdw, errMsg);
  1509.       ShowCursor (ed);
  1510.       ShowMouse (FALSE);
  1511.     ELSE
  1512.       WdwManager.SetWdwInfoline (wdw, errMsg);
  1513.     END;
  1514.   END;
  1515. END showError;
  1516.  
  1517. (*$? NOT CAT:
  1518.  
  1519. (* Funktionen und Typen fr QED-kompatible Krzeldateien 
  1520.  *)
  1521.  
  1522. TYPE shortElem = RECORD
  1523.                    val : CARDINAL;  (* ARRAY [0..1] OF CHAR interpreted als Wort *)
  1524.                    len : INTEGER;   (* L„nge des Textes *)
  1525.                    text: textPtr;   (* Der Pointer auf den Text *)
  1526.                  END;
  1527.      shortPtr  = POINTER TO shortElem;
  1528.  
  1529.      varType = (noVar, comment, string);
  1530.  
  1531. VAR shortList:      Lists.List;
  1532.     shortListRead:  BOOLEAN;
  1533.  
  1534. (*$Z-*)                   
  1535. PROCEDURE findValue (entry : ADDRESS; info : ADDRESS) : BOOLEAN;
  1536.   VAR theVar : shortPtr;
  1537.       theName: POINTER TO CARDINAL;
  1538. BEGIN
  1539.   theVar := shortPtr (entry);
  1540.   theName := info;
  1541.   RETURN theVar^.val = theName^;
  1542. END findValue;
  1543. (*$Z+*)                   
  1544.  
  1545. (*$W-*)
  1546. PROCEDURE findShortKey (short : CARDINAL; VAR var : shortPtr) : BOOLEAN;
  1547.   VAR found : BOOLEAN;
  1548. BEGIN
  1549.   Lists.ResetList (shortList);
  1550.   Lists.ScanEntries (shortList, Lists.forward, findValue, ADR (short), found);
  1551.   IF found THEN
  1552.     var := Lists.CurrentEntry (shortList);
  1553.   ELSE
  1554.     var := NIL;
  1555.   END;
  1556.   RETURN found  & (var # NIL);
  1557. END findShortKey;
  1558. (*$W+*)
  1559.  
  1560. PROCEDURE setKey (theVar : shortElem) : BOOLEAN;
  1561. (* ver„ndert eine vorhandene Variable oder erzeugt eine neue 
  1562.  *)
  1563.  VAR newVar : shortPtr;
  1564. BEGIN
  1565.   IF ~findShortKey (theVar.val, newVar)
  1566.   THEN
  1567.     ALLOCATE (newVar, TSIZE (shortElem));
  1568.     IF newVar = NIL 
  1569.     THEN RETURN FALSE
  1570.     END;
  1571.     newVar^.val  := theVar.val;
  1572.     newVar^.len  := theVar.len;
  1573.     newVar^.text := theVar.text;
  1574.     Lists.AppendEntry (shortList, newVar, v.bool);
  1575.     IF v.bool THEN RETURN FALSE END;
  1576.   ELSE
  1577.     DEALLOCATE (newVar^.text, 0);
  1578.     newVar^.text := theVar.text;
  1579.   END;
  1580.   RETURN TRUE;
  1581. END setKey;
  1582.  
  1583. PROCEDURE prep (REF in: ARRAY OF CHAR; VAR name, arg : ARRAY OF CHAR);
  1584.   VAR tmp : ARRAY [0..255] OF CHAR;
  1585.   BEGIN
  1586.     Strings.Split (in,Strings.PosLen (' ',in,0), name,arg, v.bool);
  1587.     Strings.DelLeadingBlanks (arg);
  1588.     Strings.Split (arg, Strings.PosLen ('=',arg,0)+1,tmp, arg, v.bool);
  1589.     IF arg[0] = 0C THEN Strings.Assign (tmp, arg, v.bool) END;
  1590.     Strings.DelLeadingBlanks (arg);
  1591.     (* YYYY Hier noch Semikolon-Abfrage „ndern *)
  1592.     Strings.Split (arg, Strings.PosLen (';',arg,0),arg, tmp, v.bool);
  1593.     Strings.DelLeadingBlanks (arg);
  1594.     Strings.DelTrailingBlanks (arg);
  1595.   END prep;
  1596.  
  1597. PROCEDURE getNameAndType (REF line : ARRAY OF CHAR; 
  1598.                           VAR val: CARDINAL;
  1599.                           VAR argStr : ARRAY OF CHAR): varType;
  1600.   VAR name : ARRAY [0..127] OF CHAR;
  1601. BEGIN
  1602.   prep (line, name, argStr);
  1603.   IF (name[0] = ';') OR (name[0] = '#') OR (name[0] = 0C) THEN RETURN comment END;
  1604.   IF (argStr[0] = 0C) THEN 
  1605.     RETURN noVar 
  1606.   END;
  1607.   Strings.DelLeadingBlanks (name);
  1608.   val := ORD(name[0])*255 + ORD(name[1]);
  1609.   RETURN string;
  1610. END getNameAndType;
  1611.  
  1612. PROCEDURE processLine (REF fname, line : ARRAY OF CHAR) : BOOLEAN;
  1613.   VAR theVar : shortElem;
  1614.       error  : BOOLEAN;
  1615.       argStr,
  1616.       valStr : ARRAY [0..1023] OF CHAR;
  1617.  
  1618.   PROCEDURE getInfoStr (arg : ARRAY OF CHAR; VAR str : ARRAY OF CHAR);
  1619.     VAR pos : INTEGER;
  1620.         numStr : ARRAY [0..9] OF CHAR;
  1621.         p1  : CARDINAL;
  1622.   BEGIN
  1623.       IF LENGTH (arg) > 0
  1624.       THEN
  1625.         Strings.Assign (arg,str, v.bool);
  1626.         (* Sonderzeichen bersetzen *)
  1627.         pos := 0;
  1628.         WHILE pos >= 0 DO 
  1629.           pos := Strings.Pos ('\', str, pos);
  1630.           IF pos >= 0
  1631.           THEN
  1632.             (* Feststellen, ob die n„chsten drei Zahlen sind *)
  1633.             Strings.Copy (str, pos+1, 3, numStr, v.bool);
  1634.             IF Characters.IsDigit (numStr[0])
  1635.              & Characters.IsDigit (numStr[1])
  1636.              & Characters.IsDigit (numStr[2])
  1637.             THEN
  1638.               Strings.Delete (str, pos, 4, v.bool);
  1639.               p1 := 0;
  1640.               Strings.Insert (CHR(StrConv.StrToCard (numStr, p1, v.bool)), pos, str, v.bool);
  1641.             ELSIF (numStr[0] = '\')
  1642.             THEN
  1643.               (* Ein \ entfernen *)
  1644.               Strings.Delete (str, pos, 1, v.bool);
  1645.               INC(pos);
  1646.             ELSE
  1647.               INC(pos);
  1648.             END;
  1649.           END;
  1650.         END;
  1651.       ELSE
  1652.         error := TRUE;
  1653.       END;
  1654.     END getInfoStr;
  1655.  
  1656. BEGIN
  1657.   error := FALSE;
  1658.   CASE getNameAndType (line, theVar.val, argStr) OF
  1659.     string: getInfoStr  (argStr, valStr);
  1660.             IF ~error THEN
  1661.               theVar.len := LENGTH (valStr);
  1662.               ALLOCATE (theVar.text, theVar.len+1);
  1663.               IF theVar.text = NIL THEN RETURN FALSE END;
  1664.               Strings.Assign (valStr, theVar.text^, v.bool);
  1665.             END; |
  1666.     noVar,
  1667.     comment: RETURN TRUE |
  1668.   ELSE
  1669.     error := TRUE;
  1670.   END;
  1671.   (* Variable richtig eingelesen, also weitermachen *)
  1672.   IF ~error
  1673.   THEN
  1674.     RETURN setKey (theVar);
  1675.   END;
  1676.   RETURN TRUE;
  1677. END processLine;
  1678.  
  1679. PROCEDURE FreeShortkeyList ();
  1680.   VAR theVar : shortPtr;
  1681. BEGIN
  1682.   Lists.ResetList (shortList);
  1683.   theVar := Lists.NextEntry (shortList);
  1684.   WHILE theVar # NIL DO
  1685.     Lists.RemoveEntry (shortList, v.bool);
  1686.     DEALLOCATE (theVar^.text, 0);
  1687.     DEALLOCATE (theVar, 0);
  1688.     theVar := Lists.NextEntry (shortList);
  1689.   END;
  1690.   shortListRead := FALSE;
  1691. END FreeShortkeyList;
  1692.  
  1693. PROCEDURE ReadShortkeyFile(REF fname: ARRAY OF CHAR);
  1694.   VAR s : ARRAY [0..1023] OF CHAR;
  1695.       tf    : mtTextfiles.TEXTFILE;
  1696.       cont  : BOOLEAN;
  1697. BEGIN
  1698.   IF shortListRead THEN 
  1699.     FreeShortkeyList();
  1700.   END;
  1701.   IF ~mtTextfiles.OpenTextfile (fname, mtTextfiles.READ, 8192, tf)
  1702.   THEN 
  1703.     OutOfMem();
  1704.     RETURN
  1705.   END;
  1706.   (* Jetzt Zeilenweise einlesen und dann die einzelnen Zeilen parsen *)
  1707.   REPEAT
  1708.     mtTextfiles.ReadLine (tf, s);
  1709.     mtTextfiles.ReadLn(tf);
  1710.     cont := processLine (fname, s);
  1711.   UNTIL mtTextfiles.EndofText (tf) OR ~cont;
  1712.   mtTextfiles.CloseTextfile (tf);
  1713.   shortListRead := TRUE;
  1714.   IF ~cont 
  1715.   THEN
  1716.     OutOfMem();
  1717.   END;
  1718. END ReadShortkeyFile;
  1719.  
  1720. PROCEDURE searchAndReplace (ed : EDITPTR; w, r : ARRAY OF CHAR; pos : searchPos; 
  1721.                   direction : searchDir; count : searchCount; 
  1722.                   num (* wird nur bei count = nmal benutzt *) : INTEGER;
  1723.                   ignoreCase : BOOLEAN; onlyWord : BOOLEAN; 
  1724.                   replace : BOOLEAN; ask : BOOLEAN; again : BOOLEAN;
  1725.                   doBing : BOOLEAN): BOOLEAN; FORWARD;
  1726.  
  1727. PROCEDURE SetEditShort (VAR ed: EDITPTR; theKey: shortPtr);
  1728.   VAR cLine, cl2    : LONGINT;
  1729.       cRow, cr2     : INTEGER;
  1730.       scrLine       : INTEGER;
  1731. BEGIN
  1732.   WITH ed^ DO
  1733.     (* Jetzt Position sichern *)
  1734.     cLine := currLineNr;
  1735.     cRow := currRow;
  1736.     IF putLineInEditor (ed, theKey^.text, theKey^.len, FALSE)
  1737.     THEN
  1738.       cl2 := currLineNr;
  1739.       cr2 := currRow;
  1740.       (* Jetzt die Tilde suchen und den Cursor dort positionieren *)
  1741.       IF searchAndReplace (ed, "~","", fromPos, backward, searchOne, 1, FALSE, 
  1742.                            FALSE, FALSE, FALSE, FALSE, FALSE)
  1743.       THEN
  1744.         (* Erstmal nachsehen, ob das auch im neuen Bereich ist *)
  1745.         IF (currLineNr > cLine) 
  1746.         OR ((currLineNr = cLine) & (currRow >= cRow))
  1747.         THEN
  1748.           (* Tilde entfernen *)
  1749.           Strings.Delete (editLine.text^, currRow, 1, v.bool);
  1750.           DEC (editLen);
  1751.           editChanged := TRUE;
  1752.           v.bool := EditBase.PutCurrLine (ed);
  1753.         ELSE
  1754.           (* Blockmarkierung l”schen *)
  1755.           blocks[0].blockStart.line := -1;
  1756.           blocks[0].blockEnd.line := -1;
  1757.           block := FALSE;
  1758.           SetCurrLine (ed, cl2);
  1759.           currRow := cr2;
  1760.         END;
  1761.         (* Blockmarkierung l”schen *)
  1762.         blocks[0].blockStart.line := -1;
  1763.         blocks[0].blockEnd.line := -1;
  1764.         block := FALSE;
  1765.       ELSE
  1766.         SetCurrLine (ed, cl2);
  1767.         currRow := cr2;
  1768.       END;
  1769.       (* Redraw ausl”sen *)
  1770.       IF cLine = cl2
  1771.       THEN
  1772.         redrawLineArea (ed, cLine, cLine);
  1773.       ELSE
  1774.         CenterCurrline (ed);
  1775.         scrLine := BinOps.HigherInt (0, SHORT(cLine - StartLine));
  1776.         redrawLines (ed, scrLine);
  1777.       END;
  1778.       ShowCursor (ed);
  1779.     END;
  1780.   END;
  1781. END SetEditShort;
  1782.  
  1783. PROCEDURE InsertShortkey (VAR ed: EDITPTR);
  1784.   VAR kurzVal : CARDINAL;
  1785.       theKey  : shortPtr;
  1786. BEGIN
  1787.   (* Erstmal nachsehen, ob wir so ein Krzel haben *)
  1788.   WITH ed^ DO
  1789.     IF (currRow = 0) OR block THEN RETURN END;
  1790.     IF ~shortListRead THEN RETURN END;
  1791.     IF (currRow > 1) & (editLine.text^[currRow-2] # ' ')
  1792.     THEN 
  1793.       (* Erstmal nach Zwei-Zeichen-Krzel suchen *)
  1794.       kurzVal := ORD (editLine.text^[currRow-2]) * 255 + 
  1795.                  ORD (editLine.text^[currRow-1]);
  1796.       IF findShortKey (kurzVal, theKey)
  1797.       THEN
  1798.         (* gefunden, ersetzen *)
  1799.         Strings.Delete (editLine.text^, currRow-2, 2, v.bool);
  1800.         DEC (editLen, 2);
  1801.         DEC (currRow, 2);
  1802.         editChanged := TRUE;
  1803.         v.bool := EditBase.PutCurrLine (ed);
  1804.         (* Jetzt einsetzen *)
  1805.         SetEditShort (ed, theKey);
  1806.         RETURN
  1807.       END;
  1808.     END;
  1809.     (* Jetzt nach Ein-Zeichen-Krzel suchen *)
  1810.     kurzVal := ORD (editLine.text^[currRow-1]) * 255;
  1811.     IF findShortKey (kurzVal, theKey)
  1812.     THEN
  1813.       (* gefunden, ersetzen *)
  1814.       Strings.Delete (editLine.text^, currRow-1, 1, v.bool);
  1815.       DEC (editLen);
  1816.       DEC (currRow);
  1817.       editChanged := TRUE;
  1818.       v.bool := EditBase.PutCurrLine (ed);
  1819.       (* Jetzt einsetzen *)
  1820.       SetEditShort (ed, theKey);
  1821.     END;
  1822.   END;
  1823. END InsertShortkey;
  1824.  
  1825. (* Ende von bedingter Compilierung fr Krzel *)
  1826. *)
  1827.  
  1828. (* Erweiterte Funktionen fr Search & Replace *)
  1829. PROCEDURE AskForReplace() : INTEGER;
  1830.   VAR moX, moY  : INTEGER;
  1831.       moButton  : BITSET;
  1832.       kReturn   : INTEGER;
  1833.       moKState  : BITSET;
  1834.       scan      : INTEGER;
  1835.       ch        : CHAR;
  1836.       bReturn   : INTEGER;
  1837.       event     : BITSET;
  1838.       mess      : ADDRESS;
  1839.       mrect     : Rectangle;
  1840.       valid     : BOOLEAN;
  1841. BEGIN
  1842.   valid := FALSE;
  1843.   LOOP
  1844.     (* 5 Sekunden Zeit, um eine Taste zu drcken *)
  1845.     event := MagicAES.EvntMulti(
  1846.            {MagicAES.MUKEYBD, MagicAES.MUTIMER},
  1847.            2, {0},{0}, MagicAES.LeaveRect, mrect, 0, mrect, mess, 5000, 0,
  1848.            moX, moY, moButton, kReturn, moKState, scan, ch, bReturn);
  1849.     IF MagicAES.MUTIMER IN event
  1850.     THEN
  1851.       valid := FALSE;
  1852.       EXCL (event, MagicAES.MUTIMER);
  1853.     END;
  1854.     IF MagicAES.MUKEYBD IN event
  1855.     THEN
  1856.       ch := CAP(ch);
  1857.       valid := (ch = 'J') OR (ch='N') OR (ch='Q') OR (ch ='A');
  1858.       (* Timer-Event l”schen! *)
  1859.       MagicAES.EvntTimer (1);
  1860.     END;
  1861.     IF valid THEN EXIT
  1862.     ELSE
  1863.       v.int := mtAlerts.Alert (1,askRepl);
  1864.       RETURN v.int
  1865.     END;    
  1866.   END; (* LOOP *)
  1867.   IF ch = 'J' THEN RETURN 1 ELSIF ch = 'N' THEN RETURN 2 ELSE RETURN 3 END;
  1868. END AskForReplace;
  1869.  
  1870.  
  1871. PROCEDURE Bing;
  1872. BEGIN
  1873.   CatGlobal.Bing (7);
  1874. END Bing;
  1875.  
  1876. PROCEDURE searchAndReplace (ed : EDITPTR; w, r : ARRAY OF CHAR; pos : searchPos; 
  1877.                   direction : searchDir; count : searchCount; 
  1878.                   num (* wird nur bei count = nmal benutzt *) : INTEGER;
  1879.                   ignoreCase : BOOLEAN; onlyWord : BOOLEAN; 
  1880.                   replace : BOOLEAN; ask : BOOLEAN; again : BOOLEAN;
  1881.                   doBing: BOOLEAN): BOOLEAN;
  1882. (* Suchoperationen: 
  1883.  *
  1884.  * Start:       aktuelle Position, Top, Ende
  1885.  * Richtung:    nach oben, nach unten
  1886.  * Anzahl:      erstes, ntes, letztes Vorkommen
  1887.  * Modus:       grožklein, nurWort
  1888.  *)
  1889.  VAR found : BOOLEAN;
  1890.      f2    : BOOLEAN;
  1891.      fc    : INTEGER;
  1892.      rw    : ARRAY [0..1023] OF CHAR;
  1893. BEGIN
  1894.   WITH ed^ DO 
  1895.     mtAppl.MouseBusy();
  1896.     HideCursor (ed);
  1897.     v.bool := EditBase.PutCurrLine (ed);
  1898.     findMode := SuchModus{};
  1899.     IF ignoreCase THEN INCL (findMode, GrossKlein); END;
  1900.     IF onlyWord THEN INCL (findMode, NurWort); END;
  1901.     IF replace & ~ask & (count # searchOne) THEN INCL (findMode, silent) END;
  1902.     IF ~doBing THEN INCL (findMode, silent) END;
  1903.     IF pos = fromStart
  1904.     THEN
  1905.       Home (ed, FALSE);
  1906.     END;
  1907.     found := FALSE;
  1908.     IF ~EditTools.InitSearch (ed, direction, w, rw, replace)
  1909.     THEN
  1910.       ShowCursor (ed);
  1911.       mtAppl.MouseArrow();
  1912.       RETURN FALSE
  1913.     END;
  1914.     IF count = searchOne
  1915.     THEN
  1916.       SearchWord (ed, w, direction, found, rw, again);
  1917.       IF ~found & doBing THEN Bing() 
  1918.       ELSE
  1919.         IF replace
  1920.         THEN
  1921.           IF ask
  1922.           THEN
  1923.             CenterCurrline (ed);
  1924.             v.int := AskForReplace();
  1925.             IF v.int = 1
  1926.             THEN
  1927.               ReplaceWord (ed, rw, r)
  1928. (*            ELSIF v.int = 3
  1929.             THEN 
  1930.               (* Cancel!!!, bei einmal Suchen egal *)
  1931. *)           END;
  1932.           ELSE
  1933.             ReplaceWord (ed, rw, r);
  1934.           END;
  1935.         END;
  1936.       END;
  1937.     ELSE
  1938.       found := FALSE;
  1939.       fc := 0;
  1940.       LOOP
  1941.         IF replace
  1942.         THEN
  1943.           SearchWord (ed, w, direction, f2, rw, FALSE);
  1944.         ELSE
  1945.           SearchWord (ed, w, direction, f2, rw, (fc#0) OR again);
  1946.         END;
  1947.         IF f2 THEN 
  1948.           INC (fc); 
  1949.           found := TRUE; 
  1950.           IF replace
  1951.           THEN
  1952.             IF ask
  1953.             THEN
  1954.               CenterCurrline (ed);
  1955.               v.int := AskForReplace();
  1956.               IF v.int = 1
  1957.               THEN
  1958.                 ReplaceWord (ed, rw, r)
  1959.               ELSIF v.int = 3
  1960.               THEN 
  1961.                 (* Cancel! *)
  1962.                 replace := FALSE;
  1963.                 f2 := FALSE;
  1964.               ELSE
  1965.                 (* um n„chstes zu finden *)
  1966.                 INC (currRow);
  1967.               END;
  1968.             ELSE
  1969.               ReplaceWord (ed, rw, r);
  1970.             END;
  1971.           END;
  1972.         END;
  1973.         IF ((fc >= num) & (count = searchNum)) OR ~f2 THEN EXIT END;
  1974.         IF ~replace THEN INC (currRow); END;
  1975.         EditGlobals.FixCursorPos (ed);
  1976.       END;
  1977.       IF (((count = searchNum) & ~f2) OR ~found) & doBing THEN Bing() END;
  1978.       IF found & ~f2 & ~replace THEN DEC (currRow); END;
  1979.     END;
  1980.     IF found 
  1981.     THEN
  1982.       CenterCurrline (ed);
  1983.       IF replace THEN WdwManager.RedrawWdw (ed^.wdw, ed^.editWork); END;
  1984.     END;
  1985.     (* Suchmuster wieder freigeben *)
  1986.     EditTools.EndSearch ();
  1987.     ShowCursor (ed);
  1988.   END;
  1989.   mtAppl.MouseArrow();
  1990.   RETURN found;
  1991. END searchAndReplace;
  1992.  
  1993. (*
  1994. PROCEDURE searchAndReplace (ed : EDITPTR; w, r : ARRAY OF CHAR; pos : searchPos; 
  1995.                   direction : searchDir; count : searchCount; 
  1996.                   num (* wird nur bei count = nmal benutzt *) : INTEGER;
  1997.                   ignoreCase : BOOLEAN; onlyWord : BOOLEAN; 
  1998.                   replace : BOOLEAN; ask : BOOLEAN; again : BOOLEAN;
  1999.                   doBing: BOOLEAN): BOOLEAN;
  2000. (* Suchoperationen: 
  2001.  *
  2002.  * Start:       aktuelle Position, Top, Ende
  2003.  * Richtung:    nach oben, nach unten
  2004.  * Anzahl:      erstes, ntes, letztes Vorkommen
  2005.  * Modus:       grožklein, nurWort
  2006.  *)
  2007.  VAR found : BOOLEAN;
  2008.      f2    : BOOLEAN;
  2009.      fc    : INTEGER;
  2010.      rw    : ARRAY [0..1023] OF CHAR;
  2011. BEGIN
  2012.   WITH ed^ DO 
  2013.     mtAppl.MouseBusy();
  2014.     HideCursor (ed);
  2015.     v.bool := EditBase.PutCurrLine (ed);
  2016.     findMode := SuchModus{};
  2017.     IF ignoreCase THEN INCL (findMode, GrossKlein); END;
  2018.     IF onlyWord THEN INCL (findMode, NurWort); END;
  2019.     IF replace & ~ask & (count # searchOne) THEN INCL (findMode, silent) END;
  2020.     IF ~doBing THEN INCL (findMode, silent) END;
  2021.     IF pos = fromStart
  2022.     THEN
  2023.       IF inBlock
  2024.       THEN
  2025.         ToBlockmark (ed, FALSE);
  2026.       ELSE
  2027.         Home (ed, FALSE);
  2028.       END;
  2029.     ELSIF pos = fromEnd 
  2030.     THEN
  2031.       IF inBlock
  2032.       THEN
  2033.         ToBlockmark (ed, TRUE);
  2034.       ELSE
  2035.         Home (ed, TRUE);
  2036.       END;
  2037.     ELSE
  2038.       IF ~inBlock & BlockIsMarked(ed^.wdw)
  2039.       THEN
  2040.         again := TRUE
  2041.       END;
  2042.     END;
  2043.     found := FALSE;
  2044.     IF ~EditTools.InitSearch (ed, direction, w, rw, replace)
  2045.     THEN
  2046.       ShowCursor (FALSE);
  2047.       mtAppl.MouseArrow();
  2048.       RETURN FALSE
  2049.     END;
  2050.     IF count = searchOne
  2051.     THEN
  2052.       SearchWord (ed, w, direction, found, rw, again);
  2053.       IF ~found & doBing THEN Bing() 
  2054.       ELSE
  2055.         (* Wegen Wildcards: Erstmal Fund heraussuchen 
  2056.         Strings.Copy (editLine.text^, blocks[0].blockStart.row, blocks[0].blockEnd.row - blocks[0].blockStart.row, rw, v.bool);
  2057.         *)
  2058.         IF replace
  2059.         THEN
  2060.           IF ask
  2061.           THEN
  2062.             CenterCurrline (ed);
  2063.             v.int := AskForReplace();
  2064.             IF v.int = 1
  2065.             THEN
  2066.               ReplaceWord (ed, rw, r)
  2067. (*            ELSIF v.int = 3
  2068.             THEN 
  2069.               (* Cancel!!!, bei einmal Suchen egal *)
  2070. *)           END;
  2071.           ELSE
  2072.             ReplaceWord (ed, rw, r);
  2073.           END;
  2074.         END;
  2075.       END;
  2076.     ELSE
  2077.       found := FALSE;
  2078.       fc := 0;
  2079.       LOOP
  2080.         IF replace
  2081.         THEN
  2082.           SearchWord (ed, w, direction, f2, rw, FALSE);
  2083.         ELSE
  2084.           SearchWord (ed, w, direction, f2, rw, (fc#0) OR again);
  2085.         END;
  2086.         IF f2 THEN 
  2087.           (* Wegen Wildcards: Erstmal Fund heraussuchen 
  2088.           Strings.Copy (editLine.text^, blocks[0].blockStart.row, blocks[0].blockEnd.row - blocks[0].blockStart.row , rw, v.bool);
  2089.           *)
  2090.           INC (fc); 
  2091.           found := TRUE; 
  2092.           IF replace
  2093.           THEN
  2094.             IF ask
  2095.             THEN
  2096.               CenterCurrline (ed);
  2097.               v.int := AskForReplace();
  2098.               IF v.int = 1
  2099.               THEN
  2100.                 ReplaceWord (ed, rw, r)
  2101.               ELSIF v.int = 3
  2102.               THEN 
  2103.                 (* Cancel! *)
  2104.                 replace := FALSE;
  2105.                 f2 := FALSE;
  2106.               ELSE
  2107.                 (* um n„chstes zu finden *)
  2108.                 INC (currRow);
  2109.               END;
  2110.             ELSE
  2111.               ReplaceWord (ed, rw, r);
  2112.             END;
  2113.           END;
  2114.         END;
  2115.         IF ((fc >= num) & (count = searchNum)) OR ~f2 THEN EXIT END;
  2116.         IF ~replace THEN INC (currRow); END;
  2117.         EditGlobals.FixCursorPos (ed);
  2118.       END;
  2119.       IF (((count = searchNum) & ~f2) OR ~found) & doBing THEN Bing() END;
  2120.       IF found & ~f2 & ~replace THEN DEC (currRow); END;
  2121.     END;
  2122.     IF found 
  2123.     THEN
  2124.       CenterCurrline (ed);
  2125.       IF replace THEN WdwManager.RedrawWdw (ed^.wdw, ed^.editWork); END;
  2126.     END;
  2127.     (* Suchmuster wieder freigeben *)
  2128.     EditTools.EndSearch ();
  2129.     ShowCursor (ed);
  2130.   END;
  2131.   mtAppl.MouseArrow();
  2132.   RETURN found;
  2133. END searchAndReplace;
  2134. *)
  2135.  
  2136. PROCEDURE JoinLines (ed : EDITPTR; appendSpace : BOOLEAN);
  2137. (* Fgt die aktuelle und die folgende Zeile zu einer zusammen 
  2138.  *)
  2139.  VAR newText,
  2140.      tx2      : textPtr;
  2141.      newLen   : INTEGER;
  2142.      len, len2: INTEGER;
  2143.      putLine  : LONGINT;
  2144. BEGIN
  2145.   WITH ed^ DO
  2146.     IF currLineNr < totalLineNr - 1
  2147.     THEN
  2148.       IF EditBase.GetLineLength (ed, currLineNr+1, len)
  2149.       THEN
  2150.         len2 := len;
  2151.         (* Neue L„nge berechnen *)
  2152.         newLen := len + editLen; 
  2153.         INC (newLen);
  2154.         ALLOCATE (newText, newLen+2);
  2155.         IF newText = NIL THEN RETURN END;
  2156.         (* Zeile holen *)
  2157.         v.bool := EditBase.GetLine (ed, currLineNr, newText^, len);
  2158.         (* Jetzt CR/LFs am Ende der Zeile l”schen *)
  2159.         DEC (len);
  2160.         WHILE (len >= 0) & ((newText^[len] = CR) OR (newText^[len] = LF)) DO
  2161.           newText^[len] := 0C; DEC (len);
  2162.         END;
  2163.         (* Eventuell ein Leerzeichen anh„ngen *)
  2164.         len := (*SYSTEM.*)LENGTH (newText^);
  2165.         IF (len > 0) & appendSpace & ~(newText^[len-1] IN CharSet{' ','-'}) THEN 
  2166.           newText^[len] := ' '; INC (len); 
  2167.           newText^[len] := 0C; 
  2168.         END;
  2169.         (* Jetzt n„chste Zeile holen *)
  2170.         ALLOCATE (tx2, len2+4);
  2171.         IF tx2 = NIL THEN RETURN END;
  2172.         v.bool := EditBase.GetLine (ed, currLineNr+1, tx2^, len2);
  2173.         IF ed^.umbruch THEN
  2174.           Strings.DelLeadingBlanks (tx2^);
  2175.         END;
  2176.         Strings.Append (tx2^, newText^, v.bool);
  2177.         newLen := LENGTH (newText^);
  2178.         putLine := currLineNr;
  2179.         v.bool := EditBase.DeleteLine (ed, currLineNr+1);
  2180.         v.bool := EditBase.PutLine (ed, putLine, newText^, newLen);
  2181.         editChanged := FALSE;
  2182.         EditTools.UpdateCurrLine (ed, putLine);
  2183.         DEALLOCATE (newText, 0);
  2184.         DEALLOCATE (tx2, 0);
  2185.       END;
  2186.     END;
  2187.     (*
  2188.     IF currLineNr < totalLineNr - 1
  2189.     THEN
  2190.       SetCurrLine (ed, currLineNr + 1);
  2191.       IF EditBase.GetLineLength (ed, currLineNr-1, len)
  2192.       THEN
  2193.         newLen := len + editLen; 
  2194.         INC (newLen);
  2195.         ALLOCATE (newText, newLen+2);
  2196.         IF newText = NIL THEN RETURN END;
  2197.         v.bool := EditBase.GetLine (ed, currLineNr-1, newText^, len);
  2198.         (* Jetzt CR/LFs am Ende der Zeile l”schen *)
  2199.         DEC (len);
  2200.         WHILE (len >= 0) & ((newText^[len] = CR) OR (newText^[len] = LF)) DO
  2201.           newText^[len] := 0C; DEC (len);
  2202.         END;
  2203.         len := (*SYSTEM.*)LENGTH (newText^);
  2204.         IF (len > 0) & appendSpace & ~(newText^[len-1] IN CharSet{' ','-'}) THEN 
  2205.           newText^[len] := ' '; INC (len); 
  2206.           newText^[len] := 0C; 
  2207.         END;
  2208.         IF ed^.umbruch THEN
  2209.           Strings.DelLeadingBlanks (editLine.text^);
  2210.           editLen := (*SYSTEM.*)LENGTH (editLine.text^);
  2211.         END;
  2212.         Strings.Append (editLine.text^, newText^, v.bool);
  2213.         newLen := LENGTH (newText^);
  2214.         putLine := currLineNr - 1;
  2215.         v.bool := EditBase.DeleteLine (ed, currLineNr);
  2216.         v.bool := EditBase.PutLine (ed, putLine, newText^, newLen);
  2217.         editChanged := FALSE;
  2218.         EditTools.UpdateCurrLine (ed, putLine);
  2219.         DEALLOCATE (newText, 0);
  2220.       END;
  2221.     END;
  2222.     *)
  2223.   END;
  2224. END JoinLines;
  2225.  
  2226. PROCEDURE Format0 (ed : EDITPTR; forcedJoin : BOOLEAN); FORWARD;
  2227.  
  2228. PROCEDURE CheckUmbruch (ed : EDITPTR);
  2229.   VAR l, l2 : INTEGER;
  2230.       text  : textPtr;
  2231.       edLen : INTEGER;
  2232. BEGIN
  2233.   WITH ed^ DO
  2234.     IF umbruch
  2235.     THEN
  2236.       IF (currLineNr < totalLineNr - 1) & EditBase.GetLineLength (ed, currLineNr+1, l)
  2237.       THEN 
  2238.         (* Test, ob aktuelle Zeile mit CR/LF terminiert ist *)
  2239.         IF (editLen>0) & ((editLine.text^[editLen-1] = CR) OR ((editLen > 1) & (editLine.text^[editLen-2] = CR))) THEN RETURN END;
  2240.         (* Testen, ob noch ein Wort in die aktuelle Zeile pažt *)
  2241.         v.bool := EditBase.GetLineAdr (ed, currLineNr+1, text, l);
  2242.         l2 := 0;
  2243.         WHILE (text^[l2] # 0C) & (text^[l2] = ' ') DO INC (l2) END;
  2244.         IF (l2 = l) THEN RETURN END;
  2245.         IF realTabs
  2246.         THEN
  2247.           edLen := EditGlobals.RowToIndex (editLine.text^, editLen, tabSize);
  2248.         ELSE
  2249.           edLen := editLen
  2250.         END;
  2251.         IF (edLen + findNext (text, l2, l, UmbruchSet) - l2) <= rightMargin
  2252.         THEN
  2253.           Format0 (ed, FALSE);
  2254.         END;
  2255.       END;
  2256.     END;
  2257.   END;
  2258. END CheckUmbruch;
  2259.  
  2260. PROCEDURE cutEdit (ed : EDITPTR; fromOuter : BOOLEAN): BOOLEAN;FORWARD;
  2261.  
  2262. PROCEDURE Delete (ed : EDITPTR; ctrl : BOOLEAN; saveLine : BOOLEAN);
  2263. (* Neu implementiert fr neue Textstruktur 24.6.92
  2264.  *)
  2265.  VAR join : BOOLEAN;
  2266.      delChars : INTEGER;
  2267.      l2       : INTEGER;
  2268. BEGIN
  2269.   WITH ed^ DO
  2270.     saveLine := saveLine & ~block;
  2271.     IF block THEN SaveOp (ed, blockCut, FALSE); v.bool := cutEdit (ed, FALSE); RETURN END;
  2272.     HideMouse();
  2273.     HideCursor (ed);
  2274.     (* Test auf Zeilenende *)
  2275.     join := (editLine.text^[currRow] = CR) OR (editLine.text^[currRow] = LF) OR (editLine.text^[currRow] = 0C);
  2276.     ShowFileChanged(ed); (* Anzeigen, daž Text ge„ndert *)
  2277.     IF join & (currLineNr < totalLineNr - 1)
  2278.     THEN
  2279.       (* Zeile mit n„chster vereinigen *)
  2280.       v.bool := EditBase.GetLineLength (ed, currLineNr+1, l2);
  2281.       IF editLen + l2  < rightMargin THEN
  2282.         (* ok, Folgezeile pažt komplett rein *)
  2283.         v.bool := EditBase.PutCurrLine (ed);
  2284.         IF ~v.bool THEN 
  2285.           ShowCursor (ed); ShowMouse (FALSE); RETURN (* HALT *) 
  2286.         END;
  2287.         editChanged := FALSE;
  2288.         JoinLines (ed, FALSE);
  2289.         redrawLine (ed, FALSE, TRUE); (* CurrLine neu zeichnen *) 
  2290.         IF currLineNr < StartLine + LONG(windLines) THEN
  2291.          (* Scrollen bis zu einer Zeile unter currLine *)
  2292.           IF currLineNr - StartLine + 2 < LONG(windLines) THEN
  2293.             scrollRegion (ed, SHORT(currLineNr-StartLine)+1, windLines, -1);
  2294.           ELSE
  2295.             drawLine (ed, windLines-1);
  2296.           END;
  2297.         END;
  2298.         SetDocument (ed);
  2299.         (*
  2300.         drawLine (ed, windLines-1);
  2301.         drawLine (ed, windLines);
  2302.         *)
  2303.         CheckUmbruch (ed);
  2304.       ELSIF umbruch THEN
  2305.         (* Folgezeile pažt nicht komplett *)
  2306.         Format0(ed, TRUE);
  2307.       ELSE
  2308.         (* auch kein Umbruch, dann meckern *)
  2309.         HideMouse();
  2310.         MTE.info (MTE.NoFit);
  2311.         ShowMouse (FALSE);
  2312.       END;
  2313.     ELSIF ~join
  2314.     THEN
  2315.       (* L”schen in einer Zeile *)
  2316.       IF ctrl 
  2317.       THEN
  2318.         (* Anzahl der zu l”schenden Zeichen feststellen *)
  2319.         l2 := currRow;
  2320.         currRow := findNext (editLine.text, currRow, editLen, TrennSet);
  2321.         EditGlobals.FixCursorPos (ed);
  2322.         delChars := currRow;
  2323.         currRow := l2;
  2324.         DEC (delChars, currRow);
  2325.         IF delChars <= 0 THEN delChars := 1 END;
  2326.         IF delChars + currRow > editLen THEN delChars := editLen - currRow (* HALT *) END;
  2327.       ELSE
  2328.         delChars := 1;
  2329.       END;
  2330.       Strings.Delete (editLine.text^, currRow, delChars, v.bool);
  2331.       DEC (editLen, delChars);
  2332.       editChanged := TRUE;
  2333.       redrawLine (ed, FALSE, ctrl);
  2334.       CheckUmbruch (ed);
  2335.     END;
  2336.     ShowCursor(ed);
  2337.     ShowMouse (FALSE);
  2338.   END (* WITH ed^ *);
  2339. END Delete;
  2340.  
  2341. PROCEDURE Backspace(ed : EDITPTR; ctrl: BOOLEAN);
  2342. (* CursorLeft & dann Delete *)
  2343.   VAR wasBlock : BOOLEAN;
  2344. BEGIN
  2345.   WITH ed^ DO 
  2346.     wasBlock := block;
  2347.     IF block THEN SaveOp (ed, blockCut, FALSE); v.bool := cutEdit (ed, FALSE); RETURN END;
  2348.     IF (currLineNr = 0) & (currRow = 0) THEN RETURN END;
  2349.     IF ctrl THEN 
  2350.       CursorLeft (ed, {MagicAES.KCTRL});
  2351.     ELSE
  2352.       CursorLeft (ed, {});
  2353.     END;
  2354.     CenterCurrline (ed);
  2355.     Delete (ed, ctrl, ~wasBlock);
  2356.   END;
  2357. END Backspace;
  2358.  
  2359. PROCEDURE DupLine (ed : EDITPTR); 
  2360.   VAR clLineNr : LONGINT;
  2361. BEGIN
  2362.   WITH ed^ DO
  2363.     HideMouse ();
  2364.     HideCursor (ed);
  2365.     IF block THEN RETURN END;
  2366.     ShowFileChanged (ed);
  2367.     v.bool := EditBase.PutCurrLine (ed);
  2368.     IF ~EditBase.InsertLine (ed, currLineNr, editLine.text^, FALSE, editLen) THEN 
  2369.       ShowCursor (ed);
  2370.       ShowMouse (FALSE);
  2371.       RETURN (* HALT *) 
  2372.     END;
  2373.     IF currLineNr < StartLine + LONG(windLines) THEN
  2374.       (* Scrollen bis zu einer Zeile unter currLine *)
  2375.       IF currLineNr - StartLine + 2 < LONG(windLines) THEN
  2376.         scrollRegion (ed, SHORT(currLineNr - StartLine) + 1, windLines, 1);
  2377.       END;
  2378.     END;
  2379.     SetDocument (ed);
  2380.     clLineNr := currLineNr;
  2381.     IF currLineNr >= StartLine + LONG(windLines)
  2382.     THEN 
  2383.       WdwManager.ScrollDown(ed^.wdw, 1);
  2384.     END;
  2385.     SetCurrLine (ed, clLineNr);
  2386.     (* und zeichnen *)
  2387.     drawLine (ed, SHORT(currLineNr - StartLine)+1);
  2388.     ShowCursor (ed);
  2389.     ShowMouse (FALSE);
  2390.   END;
  2391. END DupLine;
  2392.  
  2393. PROCEDURE Insert (ed: EDITPTR; ch : CHAR);FORWARD;
  2394.  
  2395. PROCEDURE Tab (ed : EDITPTR; onlyIndent: BOOLEAN);
  2396.   VAR prevLine : aLinePtr;
  2397.       prevText : textPtr;
  2398.       i, j,
  2399.       spacesToInsert,
  2400.       tabsToInsert,
  2401.       l        : INTEGER;
  2402. BEGIN
  2403.   WITH ed^ DO
  2404.     HideMouse();
  2405.     HideCursor (ed);
  2406.     CenterCurrline (ed);
  2407.     IF onlyIndent 
  2408.     THEN
  2409.       (* Alle Whitespaces in Zeile darber berspringen und bis dahin einrcken  
  2410.        *)
  2411.       IF currLineNr > 0
  2412.       THEN
  2413.         v.bool := EditBase.GetLineAdr (ed, currLineNr - 1, prevText, l);
  2414.         (* Jetzt nach erstem Buchstaben suchen *)
  2415.         i := 0;
  2416.         WHILE (i < l) & ((prevText^[i] = TAB) OR (prevText^[i] = ' ')) DO INC(i) END;
  2417.         IF i > 0 THEN
  2418.           FOR j := 0 TO i-1 DO Insert (ed, prevText^[j]) END;
  2419.         END;
  2420.       END;
  2421.     ELSE
  2422.       (* Einfach entweder ein TAB einfgen oder mit Spaces auffllen bis zur n„chsten Marke 
  2423.        *)
  2424.       IF realTabs THEN
  2425.         Insert (ed, TAB);
  2426.       ELSE
  2427.         i := ((currRow DIV tabSize) + 1) * tabSize;
  2428.         spacesToInsert := i - currRow;
  2429.         IF spacesToInsert < 0 THEN spacesToInsert := 0; (* HALT *) END;
  2430.         FOR i := 0 TO spacesToInsert-1 DO Insert (ed, ' '); END;
  2431.       END;
  2432.     END;
  2433. (*    
  2434.     spacesToInsert := -1;
  2435.     IF currLineNr > 0
  2436.     THEN
  2437.       v.bool := EditBase.GetLineAdr (ed, currLineNr - 1, prevText, l);
  2438.       (* n„chsten Wortanfang in Prevline suchen *)
  2439.       i := currRow;
  2440.       IF realTabs
  2441.       THEN
  2442.         i := RowToIndex (editLine.text^, currRow, tabSize);
  2443.       END;
  2444.       IF i < l 
  2445.       THEN
  2446.         (* ok, k”nnte noch ein Wort kommen *)
  2447.         IF ~onlyIndent
  2448.         THEN
  2449.           WHILE (i < l) & (prevText^[i] # ' ') DO INC (i); END;
  2450.         END;
  2451.         WHILE (i < l) & (prevText^[i] = ' ') DO INC (i); END;
  2452.         IF realTabs
  2453.         THEN
  2454.           spacesToInsert := i-RowToIndex (editLine.text^, currRow, tabSize) - 1;
  2455.         ELSE
  2456.           spacesToInsert := i-currRow - 1;
  2457.         END;
  2458.       END;
  2459.     END;
  2460.     IF realTabs
  2461.     THEN
  2462.       IF (spacesToInsert <= 0) & ~onlyIndent
  2463.       THEN
  2464.         tabsToInsert := 1;
  2465.         spacesToInsert := 0;
  2466.       ELSE
  2467.         INC (spacesToInsert);
  2468.         tabsToInsert := spacesToInsert DIV tabSize;
  2469.         DEC (spacesToInsert, tabsToInsert * tabSize);
  2470.       END;
  2471.       FOR i := 1 TO tabsToInsert DO Insert (ed, TAB); END;
  2472.       FOR i := 0 TO spacesToInsert-1 DO Insert (ed, ' '); END;
  2473.     ELSE
  2474.       IF (spacesToInsert <= 0) & ~onlyIndent
  2475.       THEN
  2476.         i := ((currRow DIV tabSize) + 1) * tabSize;
  2477.         spacesToInsert := i - currRow;
  2478.       END;
  2479.       FOR i := 0 TO spacesToInsert DO Insert (ed, ' '); END;
  2480.     END;
  2481.     *)
  2482.     ShowCursor (ed);
  2483.     ShowMouse (FALSE);
  2484.   END; 
  2485. END Tab;
  2486.  
  2487. PROCEDURE InsertCR (ed : EDITPTR);
  2488.   VAR row       : CARDINAL;
  2489.       cRow      : INTEGER;
  2490.       cLine     : aLinePtr;
  2491.       newSize   : INTEGER;
  2492.       tBuf      : textPtr;
  2493.       copy      : ARRAY [0..1] OF Rectangle;
  2494.       l         : INTEGER;
  2495.       clLineNr  : LONGINT;
  2496.       ch        : CHAR;
  2497. BEGIN
  2498.   WITH ed^ DO
  2499.     HideMouse();
  2500.     HideCursor (ed);
  2501.     ShowFileChanged(ed);
  2502.     l := editLen;
  2503.     IF ~EditBase.PutCurrLine (ed) THEN 
  2504.       ShowCursor (ed);
  2505.       ShowMouse (FALSE);
  2506.       RETURN (* HALT *)
  2507.     END;
  2508.     IF ~EditBase.InsertCr (ed, currLineNr, currRow) THEN 
  2509.       SetCurrLine (ed, clLineNr);
  2510.       (* und zeichnen *)
  2511.       drawLine (ed, SHORT(currLineNr - StartLine));
  2512.       CenterCurrline (ed);
  2513.       ShowCursor (ed);
  2514.       ShowMouse (FALSE);
  2515.       RETURN
  2516.     END;
  2517.     (* Zeilen unter currLine kopieren *)
  2518.     IF currLineNr < StartLine + LONG(windLines) THEN
  2519.       (* Scrollen bis zu einer Zeile unter currLine *)
  2520.       IF currLineNr - StartLine + 2 < LONG(windLines) THEN
  2521.         scrollRegion (ed, SHORT(currLineNr - StartLine) + 1, windLines, 1);
  2522.       END;
  2523.     END;
  2524.     SetDocument (ed);
  2525.     SetCurrLine (ed, currLineNr + 1);
  2526.     drawLine (ed, SHORT(currLineNr - StartLine-1));
  2527.     clLineNr := currLineNr;
  2528.     IF currLineNr >= StartLine + LONG(windLines)
  2529.     THEN 
  2530.       WdwManager.ScrollDown(ed^.wdw, 1);
  2531.     END;
  2532.     SetCurrLine (ed, clLineNr);
  2533.     (* und zeichnen *)
  2534.     drawLine (ed, SHORT(currLineNr - StartLine));
  2535.     CenterCurrline (ed);
  2536.     ShowCursor (ed);
  2537.     ShowMouse (FALSE);
  2538.   END (* WITH ed^ *)
  2539. END InsertCR;
  2540.  
  2541. CONST EndSet = CharSet{15C,'.','!',':','?',')'};
  2542.  
  2543. PROCEDURE IsAbsatzEnde (ed : EDITPTR; row : INTEGER; VAR ende : BOOLEAN);
  2544. VAR tBuf     : textPtr;
  2545.     z        : INTEGER;
  2546. BEGIN
  2547.   WITH ed^ DO
  2548.     IF row > editLen THEN row := editLen END;
  2549.     IF row = 0 THEN ende := TRUE; RETURN END; 
  2550.     ende := ende OR (editLine.text^[row-1] IN EndSet) OR ((row > 1) & (editLine.text^[row-2] IN EndSet))
  2551.             OR (currLineNr + 1 >= totalLineNr);
  2552.     IF ~ende
  2553.     THEN
  2554.       v.bool := EditBase.GetLineAdr (ed, currLineNr+1, tBuf, z);
  2555.       ende := TRUE;
  2556.       DEC(z);    (* tBuf^[z] ist immer = 0C *)
  2557.       WHILE (z >= 0) & ((tBuf^[z] = LF) OR (tBuf^[z] = CR)) DO DEC (z) END;
  2558.       WHILE (z >= 0) & ende DO
  2559.         ende := tBuf^[z] = ' ';
  2560.         DEC (z);
  2561.       END;
  2562.     END;
  2563.   END;
  2564. END IsAbsatzEnde;
  2565.  
  2566. PROCEDURE Format0 (ed : EDITPTR; forcedJoin : BOOLEAN);
  2567. (* Formatiert einen Absatz neu. Dabei werden zu lange Zeilen 
  2568.  * auf die maximale Zeilenl„nge verkrzt, Autoindent wird beachtet,
  2569.  * und Leerzeichen am Zeilenanfang werden entfernt bzw. bersprungen 
  2570.  *)
  2571.  VAR tmp : aLineDesc;
  2572.      tBuf  : textPtr;
  2573.      frame : Rectangle;
  2574.      absatzEnde,
  2575.      tmpValid,
  2576.      insertNew : BOOLEAN;
  2577.      saveCh2,
  2578.      saveCh    : CHAR;
  2579.      rowAdd,
  2580.      scrLines,
  2581.      linesAdded,
  2582.      linesRemoved,
  2583.      length, newLength,
  2584.      z, l, row, newRow,
  2585.      cRow     : INTEGER;
  2586.      xNr,
  2587.      clNr,
  2588.      rdrStart,
  2589.      aEnde,
  2590.      lastLine : LONGINT;
  2591.      idx      : INTEGER;
  2592.  
  2593.   PROCEDURE JoinSomeLines();
  2594.   BEGIN
  2595.     WITH ed^ DO
  2596.       row := editLen;
  2597.       absatzEnde := FALSE;
  2598.       IsAbsatzEnde (ed, row, absatzEnde);
  2599.       (* Solange Zeilen zusammensetzen, bis rightMargin (Zeilenl„nge) berschritten ist *)
  2600.       WHILE (~absatzEnde & (newRow < rightMargin)) OR forcedJoin DO
  2601.         (* Check auf row > 0 nicht n”tig, da dann schon Absatzende ist! *)
  2602.         IF (row > 0) & ~forcedJoin
  2603.         THEN
  2604.           JoinLines (ed, TRUE);
  2605.         ELSE
  2606.           JoinLines (ed, FALSE);
  2607.           forcedJoin := FALSE;
  2608.         END;
  2609.         row := editLen;
  2610.         IsAbsatzEnde (ed, row, absatzEnde);
  2611.         WHILE (row > 0) & ((editLine.text^[row-1] = CR) OR (editLine.text^[row-1]= LF)) DO DEC (row) END;
  2612.         newRow := row;
  2613.       END;
  2614.       WHILE (row > 0) & ((editLine.text^[row-1] = CR) OR (editLine.text^[row-1]= LF)) DO DEC (row) END;
  2615.       newRow := row;
  2616.     END;
  2617.   END JoinSomeLines;
  2618.  
  2619.   PROCEDURE SplitLine();
  2620.     VAR termCh : CHAR;
  2621.         len    : INTEGER;
  2622.   BEGIN
  2623.     WITH ed^ DO
  2624.       (* Alles hinter Umbruchstelle in tmp kopieren *)
  2625.       AllocNew (tmp, row - newRow + 2);
  2626.       Strings.Copy (editLine.text^, newRow, row-newRow, tmp.text^, v.bool);
  2627.       tmpValid := TRUE;
  2628.       
  2629.       (* Aktuelle Zeile terminieren *)
  2630.       Strings.Delete (editLine.text^, newRow, row-newRow, v.bool);
  2631.       IF newRow >= editLen THEN newRow := editLen - 2; (* HALT *) END;
  2632.       editLine.text^[newRow] := LF;
  2633.       editLine.text^[newRow+1] := 0C;
  2634.       editLen := newRow+1;
  2635.       
  2636.       editChanged := TRUE;
  2637.       v.bool := EditBase.PutCurrLine (ed);
  2638.       
  2639.       (* Jetzt tmp-String bearbeiten: 
  2640.        * Erst mal CR/LF am Zeilenende l”schen.
  2641.        * Wenn kein Space und kein '-' am Ende ist, dann ein Space anfgen
  2642.        *)
  2643.       len := LENGTH (tmp.text^);
  2644.       (* Jetzt CR/LFs am Ende der Zeile l”schen *)
  2645.       DEC (len);
  2646.       WHILE (len >= 0) & ((tmp.text^[len] = CR) OR (tmp.text^[len] = LF)) DO
  2647.         tmp.text^[len] := 0C; DEC (len);
  2648.       END;
  2649.       IF len >= 0 THEN 
  2650.         termCh := tmp.text^[len];
  2651.         IF (termCh # ' ') & (termCh # '-') & ~(termCh IN EndSet) & ~absatzEnde
  2652.         THEN
  2653.           Strings.Append (' ', tmp.text^, v.bool);
  2654.         END;                      
  2655.       END;
  2656.       IF (currLineNr = clNr) & (cRow > newRow)
  2657.       THEN
  2658.         INC(clNr); (* Saveposition inkrementieren *)
  2659.         (* neue aktuelle Spalte bestimmen *)
  2660.         cRow := cRow - newRow;
  2661.       END;
  2662.     END;
  2663.   END SplitLine;
  2664.  
  2665.   PROCEDURE maySplit (text: textPtr; row : INTEGER; idx: INTEGER): BOOLEAN;
  2666.   BEGIN
  2667.     IF (row >= ed^.rightMargin) OR (ed^.realTabs & (idx >= ed^.rightMargin)) THEN RETURN TRUE
  2668.     ELSE
  2669.       RETURN ~(text^[row] IN CharSet {0C, LF, CR}) &  (* Zeilenende, nicht splitten! *)
  2670.               ( ( (row > 0) & 
  2671.                   ( (text^[row-1] IN CharSet{'(','[','{'}) OR 
  2672.                     ( (text^[row-1] IN CharSet{'"',"'"}) & (row > 1) & (text^[row-2]=' ')
  2673.                     )
  2674.                   )
  2675.                 )
  2676.                 OR ( (row > 0) & (text^[row] IN CharSet{')',']','}'}) )
  2677.               );
  2678.     END;
  2679.   END maySplit; 
  2680.  
  2681. BEGIN
  2682.   WITH ed^ DO
  2683.     tmp.length := 16;
  2684.     ALLOCATE (tmp.text, 16);
  2685.     IF tmp.text = NIL THEN RETURN END;
  2686.     tmp.text^[0] := 0C;
  2687.     HideMouse();
  2688.     HideCursor (ed);
  2689.     (* Position merken *)
  2690.     clNr := currLineNr;
  2691.     rdrStart := clNr;
  2692.     cRow := currRow;
  2693.     insertNew := FALSE;
  2694.     length := editLen;
  2695.     absatzEnde := FALSE;
  2696.     linesRemoved := 0;
  2697.     idx := 0;
  2698.     (*
  2699.      * Dafr merke ich mir die zeilennummer des Absatzanfangs und 
  2700.      * des Absatzendes
  2701.      *)
  2702.     WHILE ~absatzEnde DO
  2703.       IsAbsatzEnde (ed, editLen, absatzEnde);
  2704.       IF ~absatzEnde
  2705.       THEN
  2706.         SetCurrLine (ed, currLineNr+1);
  2707.       END; 
  2708.     END;
  2709.     aEnde := currLineNr;
  2710.     (* Wenn Zeilen wirklich vereinigt werden sollen, 
  2711.      * dann nochmal checken 
  2712.      *)
  2713.     IF forcedJoin & (aEnde = clNr) THEN
  2714.       SetCurrLine (ed, currLineNr+1);
  2715.       absatzEnde := FALSE;
  2716.       WHILE ~absatzEnde DO
  2717.         IsAbsatzEnde (ed, editLen, absatzEnde);
  2718.         IF ~absatzEnde
  2719.         THEN
  2720.           SetCurrLine (ed, currLineNr+1);
  2721.         END; 
  2722.       END;
  2723.       aEnde := currLineNr;
  2724.     END;
  2725.     absatzEnde := FALSE;
  2726.     SetCurrLine (ed, clNr);             (* Position restaurieren *)
  2727.     tmpValid := FALSE;
  2728.     WHILE ~absatzEnde (* (length >= rightMargin) & ~insertNew *)  OR forcedJoin DO
  2729.       
  2730.       JoinSomeLines();
  2731.       
  2732.       (* Wenn jetzt die L„nge der aktuellen Zeile < rightMargin ist,
  2733.        * dann war ein anderer Grund fr das Absatzende da und es muž
  2734.        * nichts mehr gemacht werden, auch kein Einfgen von irgendwelchen
  2735.        * tempor„ren Teilen
  2736.        *)
  2737.       (* In row steht die L„nge der Zeile *)
  2738.       IF realTabs 
  2739.       THEN
  2740.         idx := EditGlobals.RowToIndex (editLine.text^, newRow, tabSize);
  2741.       END;
  2742.  
  2743.       IF (newRow >= rightMargin) OR (realTabs & (idx >= rightMargin))
  2744.       THEN 
  2745.         (* Jetzt Stelle zum Splitten der aktuellen Zeile finden *)
  2746.         WHILE maySplit (editLine.text, newRow, idx) DO
  2747.           newRow := findLast (editLine.text, newRow, UmbruchSet);
  2748.           IF realTabs 
  2749.           THEN
  2750.             idx := EditGlobals.RowToIndex (editLine.text^, newRow, tabSize);
  2751.           END;
  2752.         END;
  2753.         (* Wenn Zeile nur aus einem Wort besteht,
  2754.          * dann harten Umbruch einfgen 
  2755.          *)
  2756.         IF newRow = 0
  2757.         THEN
  2758.           newRow := BinOps.LowerInt ((*SYSTEM.*)LENGTH (editLine.text^), rightMargin-2);
  2759.           IF newRow >= row THEN newRow := row - 2; (* HALT *) END;
  2760.         END;
  2761.  
  2762.         (* Aktuelle Zeile wird mit richtigem Umbruch terminiert 
  2763.          * und der Rest wird in tmp kopiert 
  2764.          *)
  2765.         SplitLine ();
  2766.  
  2767.         (* Wenn wir am Absatzende sind, dann muž tmp als neue 
  2768.          * Zeile eingefgt werden. Andernfalls wird es vor die n„chste
  2769.          * Zeile geh„ngt und dann erneut die Schleife durchlaufen
  2770.          *)
  2771.         IF absatzEnde 
  2772.         THEN
  2773.           insertNew := TRUE;
  2774.         ELSE
  2775.           (* Nicht Absatzende, also tmp in n„chste Zeile kopieren *)
  2776.           currRow := 0;
  2777.           (* Indent feststellen von aktueller Zeile *)
  2778.           IF autoIndent THEN
  2779.             WHILE (currRow <= editLen) & (editLine.text^[currRow] = ' ') & ~(ORD (editLine.text^[currRow]) < 32) DO INC (currRow) END;
  2780.           END;
  2781.           
  2782.           (* N„chste Zeile zu aktueller Zeile machen *)
  2783.           z := currRow;
  2784.           SetCurrLine (ed, currLineNr+1);
  2785.           currRow := z;
  2786.           
  2787.           (* Cursorspalte evtl. korrigieren *)
  2788.           IF clNr = currLineNr
  2789.           THEN
  2790.             INC(cRow, currRow);
  2791.           END;
  2792.  
  2793.           l := editLen; (* L„nge aktueller Zeile *)
  2794.           z := (*SYSTEM.*)LENGTH (tmp.text^); (* tmp ist 0C terminiert ohne CR/LF *)
  2795.           (* Jetzt genaue Einfgeposition bestimmen 
  2796.            * currRow zeigt Indent von vorheriger Zeile an, newRow 
  2797.            * hiernach Indent der aktuellen Zeile
  2798.            *)
  2799.  
  2800.           newRow := 0;
  2801.           IF autoIndent THEN
  2802.             WHILE (editLine.text^[newRow] = ' ') & (editLine.text^[newRow] # 0C) DO INC (newRow) END;
  2803.           END;
  2804.  
  2805.           (* Wenn indent der oberen Zeile gr”žer dem der unteren ist,
  2806.            * dann muž noch was hinzugefgt werden
  2807.            *)
  2808.           IF currRow > newRow THEN rowAdd := currRow - newRow ELSE rowAdd := 0 END;
  2809.  
  2810.           (* Jetzt feststellen, wie lang die Zeile danach wird und 
  2811.            * dann evtl. neu allozieren 
  2812.            *)
  2813.           AllocNew (editLine, l+z+rowAdd);
  2814.  
  2815.           IF currRow > newRow THEN
  2816.             (* In vorheriger Zeile mehr eingerckt: Zeile einrcken *)
  2817.             AllocNew (tmp, (*SYSTEM.*)LENGTH (tmp.text^) + CARDINAL(currRow - newRow));
  2818.             Strings.Insert (Strings.Space(currRow-newRow), 0, tmp.text^, v.bool);
  2819.             Strings.Insert (tmp.text^, newRow, editLine.text^, v.bool);
  2820.           ELSIF newRow > currRow
  2821.           THEN
  2822.             (* In vorheriger Zeile weniger Spaces am Anfang: Spaces l”schen *)
  2823.             Strings.Delete (editLine.text^, 0, newRow-currRow, v.bool);
  2824.             Strings.Insert (tmp.text^, currRow, editLine.text^, v.bool);
  2825.           ELSE
  2826.             (* dritter Fall und muž jedesmal gemacht werden: tmp einfgen *)
  2827.             Strings.Insert (tmp.text^, currRow, editLine.text^, v.bool);
  2828.           END;
  2829.  
  2830.           editLen := INTEGER((*SYSTEM.*)LENGTH (editLine.text^));
  2831.           editChanged := TRUE;
  2832.           v.bool := EditBase.PutCurrLine (ed);
  2833.           tmpValid := FALSE;
  2834.         END;
  2835.       END;
  2836.       length := editLen;
  2837.     END (* WHILE *);
  2838.     IF tmpValid
  2839.     THEN
  2840.       l := (*SYSTEM.*)LENGTH (tmp.text^);
  2841.       linesAdded := 0;
  2842.       WHILE l > 0 DO
  2843.         z := 0;
  2844.         IF autoIndent THEN
  2845.           saveCh := editLine.text^[z];
  2846.           (* Gengend Spaces einfgen *)
  2847.           WHILE (saveCh = ' ') DO
  2848.             INC (z);
  2849.             saveCh := editLine.text^[z];
  2850.           END;
  2851.           IF (saveCh # 0C) & (saveCh # CR) & (saveCh # LF) 
  2852.           THEN
  2853.             (* Autoindent nur, wenn die Zeile nicht nur aus Space besteht *)
  2854.             AllocNew (tmp, l + z);
  2855.             Strings.Insert (Strings.Space(z), 0, tmp.text^, v.bool);
  2856.             l := (*SYSTEM.*)LENGTH (tmp.text^);
  2857.           ELSE
  2858.             z := 0;
  2859.           END;
  2860.         END;
  2861.         (* Jetzt neue Zeile einfgen *)
  2862.         newRow := BinOps.LowerInt (rightMargin+5, (*SYSTEM.*)LENGTH (tmp.text^));
  2863.         IF realTabs 
  2864.         THEN
  2865.           idx := EditGlobals.RowToIndex (tmp.text^, newRow, tabSize);
  2866.         END;
  2867.         WHILE maySplit (tmp.text, newRow, idx) DO
  2868.           newRow := findLast (tmp.text, newRow, UmbruchSet);
  2869.           IF realTabs 
  2870.           THEN
  2871.             idx := EditGlobals.RowToIndex (tmp.text^, newRow, tabSize);
  2872.           END;
  2873.         END;
  2874.         IF newRow = 0
  2875.         THEN
  2876.           (* Endlosschleife verhindern, harter Umbruch! *)
  2877.           newRow := BinOps.LowerInt ((*SYSTEM.*)LENGTH (tmp.text^), rightMargin-1);
  2878.         END;
  2879.         IF newRow < l
  2880.         THEN
  2881.           saveCh := tmp.text^[newRow];
  2882.           saveCh2 := tmp.text^[newRow+1];
  2883.           tmp.text^[newRow] := LF;
  2884.           tmp.text^[newRow+1] := 0C;
  2885.         ELSE
  2886.           AllocNew (tmp, newRow+2);
  2887.           tmp.text^[newRow] := CR;
  2888.           tmp.text^[newRow+1] := LF;
  2889.           tmp.text^[newRow+2] := 0C;
  2890.           INC (newRow, 2);
  2891.         END;
  2892.         IF ~EditBase.InsertLine (ed, currLineNr, tmp.text^, FALSE, LENGTH (tmp.text^)) THEN (* HALT *) END;
  2893.         SetCurrLine (ed, currLineNr + 1);
  2894.         INC(linesAdded);
  2895.         IF newRow < l THEN
  2896.           tmp.text^[newRow] := saveCh;
  2897.           tmp.text^[newRow+1] := saveCh2;
  2898.         END;
  2899.         Strings.Delete (tmp.text^, 0, newRow, v.bool);
  2900.         currRow := z;
  2901.         IF currLineNr = clNr 
  2902.         THEN
  2903.           INC (cRow, currRow);
  2904.         END;
  2905.         l := (*SYSTEM.*)LENGTH (tmp.text^);
  2906.       END;
  2907.     END;
  2908.     lastLine := currLineNr;
  2909.     (*
  2910.     IF aEnde < lastLine
  2911.     THEN
  2912.       (* Zeilen hinzugekommen, alles unter Absatzende nach unten scrollen *)
  2913.       IF lastLine < (StartLine + LONG (windLines) - 1)
  2914.       THEN
  2915.         scrollRegion (ed, SHORT(lastLine - StartLine) + 1, windLines, SHORT(lastLine-aEnde));
  2916.         redrawLineArea (ed, lastLine, lastLine+(lastLine - aEnde));
  2917.       END;
  2918.     ELSIF aEnde > lastLine 
  2919.     THEN
  2920.       (* Zeilen entfernt, alles unter AbsatzEnde nach oben scrollen *)
  2921.       IF aEnde < (StartLine + LONG (windLines) - 1)
  2922.       THEN
  2923.         scrollRegion (ed, SHORT(aEnde - StartLine) + 1, windLines, SHORT(lastLine-aEnde));
  2924.         redrawLines (ed, windLines - SHORT(aEnde-lastLine));
  2925.       END;
  2926.     END;
  2927.     *)
  2928.     DEALLOCATE (tmp.text, 0);
  2929.     SetCurrLine (ed, clNr);
  2930.     SetDocument (ed);
  2931.     currRow := cRow;
  2932.     (* Jetzt noch redraw von Absatzstart bis Absatzende *)
  2933.     IF lastLine # aEnde
  2934.     THEN 
  2935.       redrawLines (ed, SHORT(clNr - StartLine)-1); 
  2936.     ELSE
  2937.       IF lastLine = rdrStart THEN INC (lastLine); END;
  2938.       redrawLineArea (ed, rdrStart, lastLine);
  2939.     END;
  2940.     ShowFileChanged (ed);
  2941.     ShowCursor (ed);
  2942.     ShowMouse (FALSE);
  2943.   END (* WITH ed^ DO *)
  2944. END Format0;
  2945.  
  2946. PROCEDURE Insert (ed: EDITPTR; ch : CHAR);
  2947. (* Die wichtigste Prozedur berhaupt: 
  2948.  * ein Zeichen an der Cursorposition einfgen.
  2949.  * Neu geschrieben am 11.1.92 fr Untersttzung von 
  2950.  * Fliežtextmodus und geringere Fehleranf„lligkeit.
  2951.  *)
  2952. VAR tBuf : textPtr;
  2953.     idx,
  2954.     l, z : INTEGER;
  2955.  
  2956.  PROCEDURE InsertOne ();
  2957.    VAR lastCh : CHAR;
  2958.        newLength : INTEGER;
  2959.  BEGIN
  2960.    WITH ed^ DO 
  2961.      (* Zeichen ohne Umbruch einfgen *)
  2962.      IF (editLine.length-2 <= l) OR (currRow >= editLine.length-2)
  2963.      THEN 
  2964.        (* Shit, Zeile zu kurz, umspeichern *)
  2965.        newLength := ((editLine.length DIV 16) + 1) * 16;
  2966.        IF newLength <= editLine.length THEN INC (newLength,16); END;
  2967.        ALLOCATE (tBuf, newLength);
  2968.        IF tBuf = NIL THEN 
  2969.          v.bool := EditBase.CompactBuffer (ed);
  2970.          ALLOCATE (tBuf, newLength);
  2971.          IF tBuf = NIL
  2972.          THEN
  2973.            (* kein Speicher mehr frei *) 
  2974.            RETURN (* Zeichen einfach nicht einfgen *)
  2975.            (* HALT *)
  2976.          END;
  2977.        END;
  2978.        Strings.Assign (editLine.text^, tBuf^, v.bool);
  2979.        DEALLOCATE (editLine.text, 0);
  2980.        editLine.text := tBuf;
  2981.        editLine.length := newLength;
  2982.      END;
  2983.      lastCh := editLine.text^[currRow];
  2984.      IF insertMode OR (ORD(lastCh) < 32)
  2985.      THEN
  2986.        Strings.Insert (ch, currRow, editLine.text^, v.bool);
  2987.        INC (editLen);
  2988.      ELSE
  2989.        editLine.text^[currRow] := ch;
  2990.      END;
  2991.      editChanged := TRUE;
  2992.    END; (* WITH ed^ DO *)
  2993.  END InsertOne;
  2994.  
  2995. BEGIN
  2996.   WITH ed^ DO
  2997.     (* Cursor und Mouse ausschalten *)
  2998.     HideMouse();
  2999.     HideCursor (ed);
  3000.     (* Aktuelle Zeile sichern fr Undo *)
  3001. (*    SaveLine(currLine, currLineNr); *)
  3002.     (* Bei markiertem Block diesen ersetzen und Operation fr Undo merken *)
  3003.     IF block THEN SaveOp (ed, blockToChar, FALSE); v.bool := cutEdit (ed, FALSE); END;
  3004.     (* Zeilenl„nge feststellen *)
  3005.     l := editLen;
  3006.     (* Anzeigen, das File ge„ndert *)
  3007.     ShowFileChanged (ed);
  3008.     (* Wenn Zeilenl„nge nicht zu grož ist, dann einfach einfgen *)
  3009.     IF realTabs
  3010.     THEN
  3011.       idx := EditGlobals.RowToIndex (editLine.text^, l, tabSize);
  3012.     ELSE
  3013.       idx := l
  3014.     END;
  3015.     IF (idx < rightMargin) OR (ch = CR) OR (ch = LF)
  3016.     THEN
  3017.       (* Zeichen ohne Umbruch einfgen *)
  3018.       InsertOne();
  3019.       IF (ch # CR) & (ch # LF) THEN redrawLine (ed, TRUE, FALSE); END;
  3020.       INC (currRow);
  3021.     ELSIF umbruch
  3022.     THEN
  3023.       (* Hier Absatzumbruch vornehmen! *)
  3024.       (* Jetzt aktuelle Zeile umbrechen *)
  3025.       IF (currRow >= l) & (ch = ' ') & (editLine.text^[l-1] = ' ')
  3026.       THEN
  3027.         (* Am Ende der Zeile Space einfgen => Sprung in n„chste Zeile 
  3028.          * und dort Space einfgen
  3029.          *)
  3030.         IF currLineNr - 1 < totalLineNr
  3031.         THEN
  3032.           IF autoIndent THEN 
  3033.             (* findFirstWord in CurrLine *) 
  3034.             currRow := 0;
  3035.             WHILE (editLine.text^[currRow] = ' ') & ~(ORD (editLine.text^[currRow]) < 32) DO
  3036.               INC (currRow) 
  3037.             END;
  3038.           ELSE currRow := 0 END;
  3039.           z := currRow;
  3040.           (* n„chste Zeile zur aktuellen machen *)
  3041.           SetCurrLine (ed, currLineNr+1);
  3042.           currRow := z;
  3043.         ELSE
  3044.           (* Zeile einfgen mit Autoindent-Beachtung *)
  3045.           Insert (ed, LF);
  3046.           InsertCR(ed);
  3047.           currRow := 0; 
  3048.           IF autoIndent THEN Tab (ed, TRUE); END;
  3049.         END; (* IF currLine^.next # NIL *)
  3050.         Insert(ed, ch);
  3051.       ELSE
  3052.         (* Zeichen einfach einfgen und danach Absatzformatierung ausl”sen *)
  3053.         InsertOne();
  3054.         INC (currRow);
  3055.         Format0 (ed, FALSE);
  3056.       END;
  3057.     ELSE
  3058.       (* Zeile zu lang und kein Umbruch! *)
  3059.       (* Ein Bing ausgeben *)
  3060.       MagicDOS.Cconout (7C);       
  3061.     END;
  3062.     ShowCursor (ed);
  3063.     ShowMouse (FALSE);
  3064.   END (* WITH ed^ *)
  3065. END Insert;
  3066.  
  3067.                 (* Clipboard-Funktionen *)
  3068.  
  3069. PROCEDURE cutBlock (ed : EDITPTR; toClip, redraw : BOOLEAN): BOOLEAN;
  3070. VAR   cLine : LONGINT;
  3071.       l     : LONGINT;
  3072.       clNr  : LONGINT;
  3073.       rdrStart : INTEGER;
  3074.       rdrLines : LONGINT;
  3075.       ende,
  3076.       addCr,
  3077.       oneLine  : BOOLEAN;
  3078.       bStart,
  3079.       blEnd,
  3080.       blStart  : LONGINT;
  3081. BEGIN
  3082.   WITH ed^ DO
  3083.     v.bool := EditBase.PutCurrLine(ed);
  3084.     addCr := FALSE;
  3085.     bStart := blocks[0].blockStart.line;
  3086.     IF (blocks[0].blockStart.line >= 0) & (blocks[0].blockEnd.line >= 0)
  3087.     THEN
  3088.       (* Jetzt erstmal Blockmarkierung auf gltige Bereiche beschr„nken *)
  3089.       IF blocks[0].blockEnd.line > totalLineNr - 1 
  3090.       THEN
  3091.         SetCurrLine (ed, totalLineNr - 1);
  3092.         currRow := editLen;
  3093.         blocks[0].blockEnd.row := currRow;
  3094.         blocks[0].blockEnd.line := currLineNr
  3095.       END;
  3096.       
  3097.       (* Redraw-Bereich feststellen *)
  3098.       IF (blocks[0].blockStart.line >= StartLine) & (blocks[0].blockStart.line < StartLine + LONG(windLines))
  3099.       THEN
  3100.         rdrStart := SHORT(blocks[0].blockStart.line-StartLine);
  3101.       ELSE
  3102.         rdrStart := -1;
  3103.       END;
  3104.       (* Block auf Clipboard schieben *)
  3105.       IF toClip THEN 
  3106.         IF ~CatEdit.EditCopy (wdw) 
  3107.         THEN
  3108.           RETURN FALSE
  3109.         END; 
  3110.       END;
  3111.  
  3112.       SetCurrLine (ed, blocks[0].blockStart.line);
  3113.       currRow := blocks[0].blockStart.row;
  3114.       rdrLines := blocks[0].blockEnd.line - blocks[0].blockStart.line;
  3115.  
  3116.       (* Jetzt Block l”schen *)
  3117.       IF (blocks[0].blockStart.line = blocks[0].blockEnd.line) 
  3118.       OR ((blocks[0].blockEnd.line = blocks[0].blockStart.line+1) 
  3119.         & (blocks[0].blockEnd.row = 0) 
  3120.         & (blocks[0].blockStart.row = 0))
  3121.       THEN 
  3122.         (* Flag fr Redraw setzen! *)
  3123.         oneLine := TRUE;
  3124.         (* Nur Block in einer Zeile *)
  3125.         IF ((blocks[0].blockStart.row = 0) & (blocks[0].blockEnd.row = editLen)) OR 
  3126.            ((blocks[0].blockStart.row = 0) & (blocks[0].blockEnd.row = 0) & (blocks[0].blockStart.line = blocks[0].blockEnd.line-1))
  3127.         THEN 
  3128.           (* Wenn die gel”schte Zeile ein Absatzende enth„lt und die 
  3129.            * darber nicht, dann muž an die darber ein Absatzende gesetzt 
  3130.            * werden 
  3131.            *)
  3132.           ende := FALSE;
  3133.           IsAbsatzEnde (ed, editLen, ende);
  3134.           IF ende & (blocks[0].blockStart.line > 0)
  3135.           THEN
  3136.             (* Jetzt die Zeile vorher kontrollieren *)
  3137.             SetCurrLine (ed, blocks[0].blockStart.line - 1);
  3138.             ende := FALSE;
  3139.             IsAbsatzEnde (ed, editLen, ende);
  3140.             IF ~ende
  3141.             THEN
  3142.               addCr := TRUE;
  3143.             END;
  3144.             SetCurrLine (ed, blocks[0].blockStart.line);
  3145.           END;
  3146.           (* Blockmarkierung l”schen *)
  3147.           EditTools.ClearBlock (ed);
  3148.           (* Genau eine Zeile markiert *)
  3149.           DeleteLine (ed, TRUE);
  3150.           (* Redraw wird schon bei DeleteLine gemacht *)
  3151.           redraw := FALSE;
  3152.         ELSE
  3153.           Strings.Delete (editLine.text^, blocks[0].blockStart.row, blocks[0].blockEnd.row-blocks[0].blockStart.row, v.bool);
  3154.           editChanged := TRUE;
  3155.           editLen := (*SYSTEM.*)LENGTH (editLine.text^);
  3156.         END;
  3157.       ELSE
  3158.         oneLine := FALSE;
  3159.         (* mehrzeiliger Block *)
  3160.         l := blocks[0].blockStart.line;
  3161.         IF blocks[0].blockEnd.line - blocks[0].blockStart.line - 2 > 0 
  3162.         THEN
  3163.           blEnd := blocks[0].blockEnd.line;
  3164.           blStart := blocks[0].blockStart.line;
  3165.           (* Erstmal Ende und Anfang bearbeiten *)
  3166.           SetCurrLine (ed, blocks[0].blockStart.line);
  3167.           WITH editLine DO
  3168.             IF blocks[0].blockStart.row > 0 THEN
  3169.               (* Nur Teilweise l”schen *)
  3170.               Strings.Delete (text^, blocks[0].blockStart.row, editLen-blocks[0].blockStart.row, v.bool);
  3171.               DEC (editLen, editLen - blocks[0].blockStart.row);
  3172.               editChanged := TRUE;
  3173.               v.bool := EditBase.PutCurrLine(ed);
  3174.             ELSE
  3175. (*              DeleteLine (ed, FALSE); *)
  3176.               DEC (blStart);
  3177. (*              DEC (blEnd); *)
  3178.             END;
  3179.           END;
  3180.           SetCurrLine (ed, blEnd);
  3181.           WITH editLine DO
  3182.             IF (blocks[0].blockEnd.row < length) THEN
  3183.               (* ebenfalls nur teilweise l”schen *)
  3184.               Strings.Delete (text^, 0, blocks[0].blockEnd.row, v.bool);
  3185.               DEC (editLen, blocks[0].blockEnd.row);
  3186.               editChanged := TRUE;
  3187.               v.bool := EditBase.PutCurrLine(ed);
  3188.             ELSE
  3189. (*              DeleteLine (ed, FALSE); *)
  3190.               ende := FALSE;
  3191.               IsAbsatzEnde (ed, editLen, ende);
  3192.               IF ende & (blocks[0].blockStart.line > 0)
  3193.               THEN
  3194.                 (* Jetzt die Zeile vorher kontrollieren *)
  3195.                 SetCurrLine (ed, blocks[0].blockStart.line - 1);
  3196.                 ende := FALSE;
  3197.                 IsAbsatzEnde (ed, editLen, ende);
  3198.                 IF ~ende
  3199.                 THEN
  3200.                   addCr := TRUE;
  3201.                 END;
  3202.               END;
  3203.               INC (blEnd);
  3204.             END;
  3205.           END (* WITH editLine *);
  3206.           (* Und jetzt die grobe Harke *)
  3207.           v.bool := EditBase.DeleteSomeLines (ed, blStart+1, blEnd-1);
  3208.           SetCurrLine (ed, blocks[0].blockStart.line);
  3209.           currRow := blocks[0].blockStart.row;
  3210.         ELSE
  3211.           blEnd := blocks[0].blockEnd.line;
  3212.           WHILE l <= blEnd DO
  3213.             SetCurrLine (ed, l);
  3214.             WITH editLine DO
  3215.               IF (l = blocks[0].blockStart.line) & (blocks[0].blockStart.row > 0) THEN
  3216.                 (* Nur Teilweise l”schen *)
  3217.                 Strings.Delete (text^, blocks[0].blockStart.row, editLen-blocks[0].blockStart.row, v.bool);
  3218.                 DEC (editLen, editLen - blocks[0].blockStart.row);
  3219.                 editChanged := TRUE;
  3220.                 INC(l);
  3221.               ELSIF (l = blEnd) & (blocks[0].blockEnd.row < length) THEN
  3222.                 (* ebenfalls nur teilweise l”schen *)
  3223.                 Strings.Delete (text^, 0, blocks[0].blockEnd.row, v.bool);
  3224.                 DEC (editLen, blocks[0].blockEnd.row);
  3225.                 editChanged := TRUE;
  3226.                 INC(l);
  3227.               ELSE
  3228.                 DeleteLine (ed, FALSE);
  3229.                 DEC (blEnd);
  3230.               END;
  3231.             END (* WITH editLine *);
  3232.           END (* WHILE *);
  3233.         END;
  3234.         (* Join lines if necessary *)
  3235.         IF blocks[0].blockStart.row > 0 THEN 
  3236.           SetCurrLine (ed, blocks[0].blockStart.line); 
  3237.           currRow := blocks[0].blockStart.row; 
  3238.           EditTools.ClearBlock (ed); 
  3239.           Delete (ed, FALSE, FALSE);
  3240.         END;
  3241.       END; (* IF blockStart.line = blockEnd.line *)
  3242.     
  3243.       v.bool := EditBase.PutCurrLine(ed);
  3244.       
  3245.       (* Jetzt nachsehen, ob ein CR hinzugefgt werden muž *)
  3246.       IF addCr 
  3247.       THEN
  3248.         cLine := currLineNr;
  3249.         SetCurrLine (ed, bStart-1);
  3250.         AllocNew (editLine, editLen + 4);
  3251.         Protect (editLine.text);
  3252.         editChanged := TRUE;
  3253.         editLen := (*SYSTEM.*)LENGTH (editLine.text^);
  3254.         v.bool := EditBase.PutCurrLine (ed);
  3255.         IF ~redraw
  3256.         THEN
  3257.           redraw := bStart-1 >= StartLine;
  3258.           rdrStart := SHORT(bStart-1-StartLine);
  3259.           oneLine := TRUE;
  3260.         ELSIF rdrStart > 0 
  3261.         THEN
  3262.           DEC (rdrStart)
  3263.         END;
  3264.         SetCurrLine (ed, cLine);
  3265.       END;
  3266.       (* Blockmarken l”schen *)
  3267.       EditTools.ClearBlock (ed);
  3268.       SetDocument (ed);
  3269.     
  3270.       EditTools.UpdateCurrLine (ed, currLineNr);
  3271.       (* Jetzt nur noch neu Zeichnen *)
  3272.       IF redraw
  3273.       THEN
  3274.         IF rdrStart >= 0
  3275.         THEN
  3276.           IF oneLine
  3277.           THEN
  3278.             drawLine (ed, rdrStart);
  3279.           ELSIF rdrLines < LONG (windLines) 
  3280.           THEN
  3281.             redrawLines (ed, rdrStart-1);
  3282.           ELSE
  3283.             CenterCurrline (ed);
  3284.             WdwManager.RedrawWdw (ed^.wdw, editWork)
  3285.           END;
  3286.         ELSE
  3287.           CenterCurrline (ed);
  3288.           WdwManager.RedrawWdw (ed^.wdw, editWork);
  3289.         END;
  3290.       END;
  3291.     END; (* IF blockDa *)
  3292.   END (* WITH ed^ DO *);
  3293.   RETURN TRUE;
  3294. END cutBlock;
  3295.  
  3296. PROCEDURE cutEdit (ed : EDITPTR; fromOuter : BOOLEAN): BOOLEAN;
  3297.  VAR res: BOOLEAN;
  3298. BEGIN
  3299.   IF ed^.readOnly THEN RETURN FALSE END;
  3300.   IF fromOuter THEN SaveOp (ed, blockCut, FALSE); END;
  3301.   ShowFileChanged(ed); (* Anzeigen, daž Text ge„ndert *)
  3302.   res := cutBlock (ed, fromOuter, TRUE);
  3303.   CenterCurrline (ed);
  3304.   IF ed^.showInfo THEN SetInfoLine (ed); END;
  3305.   RETURN res;
  3306. END cutEdit;
  3307.  
  3308. PROCEDURE putLineInEditor (ed: EDITPTR; adr: ADDRESS; len: CARDINAL; redraw: BOOLEAN): BOOLEAN;
  3309. (* Fgt einen Text an adr an die aktuelle Position ein! 
  3310.  *)
  3311.  VAR blStart  : LONGINT;
  3312.      scrLine  : INTEGER;
  3313.      wasBlock : BOOLEAN;
  3314.      adr2     : ADDRESS;
  3315. BEGIN
  3316.   WITH ed^ DO 
  3317.     IF readOnly OR (len = 0) THEN RETURN TRUE END;
  3318.     (* Der Text an adr wird hier dupliziert, da der Speicher 
  3319.      * danach in der Leseroutine freigegeben wird
  3320.      *)
  3321.     ALLOCATE (adr2, len);
  3322.     IF adr2=NIL
  3323.     THEN
  3324.       OutOfMem();
  3325.       RETURN FALSE
  3326.     END;
  3327.     Block.Copy (adr,len, adr2);
  3328.     HideMouse();
  3329.     HideCursor (ed);
  3330.     v.bool := EditBase.PutCurrLine (ed);
  3331.     wasBlock := block;
  3332.     IF block THEN 
  3333.       SaveOp (ed, blockPaste, FALSE); 
  3334.       v.bool := cutBlock (ed, FALSE, FALSE); 
  3335.     ELSE
  3336.       SaveOp (ed, normalPaste, FALSE);
  3337.     END;
  3338.     SetBlockstart (ed);
  3339.     block := TRUE;
  3340.     IF ~EditBase.InsertBuffer (ed, adr2, len, TRUE)
  3341.     THEN
  3342.       (* Fehlermeldung *)
  3343.       blocks[0].blockStart.line := -1;
  3344.       blocks[0].blockEnd.line := -1;
  3345.       block := FALSE;
  3346.       OutOfMem();
  3347.       ShowCursor (ed);
  3348.       ShowMouse (FALSE);
  3349.       RETURN FALSE
  3350.     END;
  3351. (*      DEALLOCATE (adr2, 0); *)
  3352.     NewBlockToUndoBuffer (ed);
  3353.     blStart := blocks[0].blockStart.line;
  3354.     SetCurrLine (ed, blocks[0].blockEnd.line);
  3355.     currRow := blocks[0].blockEnd.row;
  3356.     IF ~wasBlock THEN 
  3357.       (* normal Paste *) 
  3358.       block := FALSE; 
  3359.       blocks[0].blockStart.line := -1; 
  3360.       blocks[0].blockEnd.line := -1; 
  3361.     END;
  3362.     EditTools.UpdateCurrLine (ed, currLineNr);
  3363.     EditGlobals.FixCursorPos (ed);
  3364.     SetDocument (ed);
  3365.     ShowFileChanged (ed);
  3366.     IF redraw
  3367.     THEN
  3368.       CenterCurrline (ed);
  3369.       scrLine := BinOps.HigherInt (0, SHORT(blStart - StartLine));
  3370.       redrawLines (ed, scrLine);
  3371.     END;
  3372.     ShowCursor (ed);
  3373.     ShowMouse (FALSE);
  3374.   END;
  3375.   RETURN TRUE
  3376. END putLineInEditor;
  3377.  
  3378. BEGIN
  3379.   editList := NIL;
  3380.   rotateFaktor := 13;
  3381.   (*$? NOT CAT:
  3382.   Lists.CreateList (shortList, v.bool);
  3383.   shortListRead := FALSE;
  3384.   *)
  3385. END EditFuncs.
  3386.  
  3387.